@open-mercato/core 0.7.0 → 0.7.1-develop.7103.1.41ff100d93
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 +14 -9
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +5 -5
- 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 +17 -9
- package/src/modules/customers/api/deals/map/route.ts +4 -4
- 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
|
@@ -28,7 +28,10 @@ export const metadata = {
|
|
|
28
28
|
|
|
29
29
|
type WidgetContext = WidgetScopeContext & { limit: number }
|
|
30
30
|
|
|
31
|
-
async function resolveContext(
|
|
31
|
+
async function resolveContext(
|
|
32
|
+
req: Request,
|
|
33
|
+
translate: (key: string, fallback?: string) => string,
|
|
34
|
+
): Promise<WidgetContext> {
|
|
32
35
|
const url = new URL(req.url)
|
|
33
36
|
const rawQuery: Record<string, string> = {}
|
|
34
37
|
for (const [key, value] of url.searchParams.entries()) {
|
|
@@ -39,16 +42,18 @@ async function resolveContext(req: Request, translate: (key: string, fallback?:
|
|
|
39
42
|
throw new CrudHttpError(400, { error: translate('customers.errors.invalid_query', 'Invalid query parameters') })
|
|
40
43
|
}
|
|
41
44
|
|
|
42
|
-
const { container, em, tenantId, organizationIds } =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
const { container, em, tenantId, organizationIds, isUnrestrictedOrganizationScope } =
|
|
46
|
+
await resolveWidgetScope(req, translate, {
|
|
47
|
+
tenantId: parsed.data.tenantId ?? null,
|
|
48
|
+
organizationId: parsed.data.organizationId ?? null,
|
|
49
|
+
})
|
|
46
50
|
|
|
47
51
|
return {
|
|
48
52
|
container,
|
|
49
53
|
em,
|
|
50
54
|
tenantId,
|
|
51
55
|
organizationIds,
|
|
56
|
+
isUnrestrictedOrganizationScope,
|
|
52
57
|
limit: parsed.data.limit,
|
|
53
58
|
}
|
|
54
59
|
}
|
|
@@ -56,7 +61,8 @@ async function resolveContext(req: Request, translate: (key: string, fallback?:
|
|
|
56
61
|
export async function GET(req: Request) {
|
|
57
62
|
const { translate } = await resolveTranslations()
|
|
58
63
|
try {
|
|
59
|
-
const { container, em, tenantId, organizationIds, limit } =
|
|
64
|
+
const { container, em, tenantId, organizationIds, isUnrestrictedOrganizationScope, limit } =
|
|
65
|
+
await resolveContext(req, translate)
|
|
60
66
|
const auth = {
|
|
61
67
|
tenantId,
|
|
62
68
|
orgId: organizationIds?.[0] ?? null,
|
|
@@ -64,6 +70,7 @@ export async function GET(req: Request) {
|
|
|
64
70
|
}
|
|
65
71
|
const flags = await resolveCustomerInteractionFeatureFlags(container, tenantId)
|
|
66
72
|
const mergedWindow = Math.min(limit * 4, 50)
|
|
73
|
+
const isUnrestricted = isUnrestrictedOrganizationScope === true
|
|
67
74
|
const rows = flags.unified
|
|
68
75
|
? (await listCanonicalTodoRows(
|
|
69
76
|
em,
|
|
@@ -71,7 +78,7 @@ export async function GET(req: Request) {
|
|
|
71
78
|
auth,
|
|
72
79
|
organizationIds?.[0] ?? null,
|
|
73
80
|
organizationIds ?? null,
|
|
74
|
-
{ pagination: { page: 1, pageSize: limit } },
|
|
81
|
+
{ pagination: { page: 1, pageSize: limit }, isUnrestricted },
|
|
75
82
|
)).items
|
|
76
83
|
: await Promise.all([
|
|
77
84
|
listLegacyTodoRows(
|
|
@@ -80,7 +87,7 @@ export async function GET(req: Request) {
|
|
|
80
87
|
tenantId,
|
|
81
88
|
organizationIds ?? null,
|
|
82
89
|
undefined,
|
|
83
|
-
{ limit: mergedWindow },
|
|
90
|
+
{ limit: mergedWindow, isUnrestricted },
|
|
84
91
|
),
|
|
85
92
|
listCanonicalTodoRows(
|
|
86
93
|
em,
|
|
@@ -91,6 +98,7 @@ export async function GET(req: Request) {
|
|
|
91
98
|
{
|
|
92
99
|
includeDeleted: true,
|
|
93
100
|
limit: mergedWindow,
|
|
101
|
+
isUnrestricted,
|
|
94
102
|
},
|
|
95
103
|
),
|
|
96
104
|
]).then(([legacyRows, canonicalRows]) =>
|
|
@@ -101,8 +101,11 @@ export async function GET(req: Request, ctx: { params?: { id?: string } }) {
|
|
|
101
101
|
throw notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
// Existence oracle (#5504): deny a cross-org read as not-found — identical to
|
|
105
|
+
// the parent-not-found above — so it cannot reveal that a deal exists in an
|
|
106
|
+
// organization the caller cannot see.
|
|
104
107
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: deal.organizationId })) {
|
|
105
|
-
throw
|
|
108
|
+
throw notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
106
109
|
}
|
|
107
110
|
|
|
108
111
|
const entityScope = { tenantId: deal.tenantId, organizationId: deal.organizationId }
|
|
@@ -102,8 +102,11 @@ export async function GET(req: Request, ctx: { params?: { id?: string } }) {
|
|
|
102
102
|
throw notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
// Existence oracle (#5504): deny a cross-org read as not-found — identical to
|
|
106
|
+
// the parent-not-found above — so it cannot reveal that a deal exists in an
|
|
107
|
+
// organization the caller cannot see.
|
|
105
108
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: deal.organizationId })) {
|
|
106
|
-
throw
|
|
109
|
+
throw notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
const entityScope = { tenantId: deal.tenantId, organizationId: deal.organizationId }
|
|
@@ -19,10 +19,9 @@ import type { ActionLogService } from '@open-mercato/core/modules/audit_logs/ser
|
|
|
19
19
|
import { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'
|
|
20
20
|
import { normalizeCustomFieldResponse } from '@open-mercato/shared/lib/custom-fields/normalize'
|
|
21
21
|
import { E } from '#generated/entities.ids.generated'
|
|
22
|
-
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
23
22
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
24
23
|
import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
25
|
-
import {
|
|
24
|
+
import { denyCustomerDetailReadAsNotFound } from '../../../lib/detailReadAccess'
|
|
26
25
|
import { decryptEntitiesWithFallbackScope } from '@open-mercato/shared/lib/encryption/subscriber'
|
|
27
26
|
import { runWithCacheTenant } from '@open-mercato/cache'
|
|
28
27
|
import {
|
|
@@ -47,10 +46,6 @@ function notFound(message: string) {
|
|
|
47
46
|
return NextResponse.json({ error: message }, { status: 404 })
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
function forbidden(message: string) {
|
|
51
|
-
return NextResponse.json({ error: message }, { status: 403 })
|
|
52
|
-
}
|
|
53
|
-
|
|
54
49
|
type DealAssociation = {
|
|
55
50
|
id: string
|
|
56
51
|
label: string
|
|
@@ -416,23 +411,10 @@ export async function GET(request: Request, context: { params?: Record<string, u
|
|
|
416
411
|
return NextResponse.json({ error: 'Authentication required' }, { status: 401 })
|
|
417
412
|
}
|
|
418
413
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
rbac = null
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (!rbac || !auth?.sub) {
|
|
427
|
-
return forbidden('Access denied')
|
|
428
|
-
}
|
|
429
|
-
const hasFeature = await rbac.userHasAllFeatures(auth.sub, ['customers.deals.view'], {
|
|
430
|
-
tenantId: auth.tenantId ?? null,
|
|
431
|
-
organizationId: auth.orgId ?? null,
|
|
432
|
-
})
|
|
433
|
-
if (!hasFeature) {
|
|
434
|
-
return forbidden('Access denied')
|
|
435
|
-
}
|
|
414
|
+
// The API dispatcher already enforces `requireFeatures: ['customers.deals.view']`
|
|
415
|
+
// against the caller's effective (selected) organization before this handler
|
|
416
|
+
// runs, so no in-route feature re-check is needed. Re-checking here against the
|
|
417
|
+
// token org (auth.orgId) would wrongly 403 org-switched callers (#5012).
|
|
436
418
|
|
|
437
419
|
const scope = await resolveOrganizationScopeForRequest({ container, auth, request })
|
|
438
420
|
const em = (container.resolve('em') as EntityManager)
|
|
@@ -454,9 +436,16 @@ export async function GET(request: Request, context: { params?: Record<string, u
|
|
|
454
436
|
return notFound('Deal not found')
|
|
455
437
|
}
|
|
456
438
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
439
|
+
// Existence oracle (issue #5504): a caller who holds customers.deals.view but
|
|
440
|
+
// whose scope excludes the record's organization must get the SAME response as
|
|
441
|
+
// for a non-existent id, so 403-when-present / 404-when-absent collapses to a
|
|
442
|
+
// uniform 404 not-found. The dispatcher already returns a uniform 403 for
|
|
443
|
+
// callers who lack the feature entirely.
|
|
444
|
+
const organizationReadDenied = denyCustomerDetailReadAsNotFound(
|
|
445
|
+
{ scope, auth, organizationId: deal.organizationId },
|
|
446
|
+
'Deal not found',
|
|
447
|
+
)
|
|
448
|
+
if (organizationReadDenied) return organizationReadDenied
|
|
460
449
|
|
|
461
450
|
const decryptionScope = {
|
|
462
451
|
tenantId: deal.tenantId ?? auth.tenantId ?? null,
|
|
@@ -977,8 +966,8 @@ export const openApi: OpenApiRouteDoc = {
|
|
|
977
966
|
],
|
|
978
967
|
errors: [
|
|
979
968
|
{ status: 401, description: 'Unauthorized', schema: dealDetailErrorSchema },
|
|
980
|
-
{ status: 403, description: 'Forbidden
|
|
981
|
-
{ status: 404, description: 'Deal not found', schema: dealDetailErrorSchema },
|
|
969
|
+
{ status: 403, description: 'Forbidden — caller lacks the required feature', schema: dealDetailErrorSchema },
|
|
970
|
+
{ status: 404, description: 'Deal not found, or its organization is not in the caller’s scope', schema: dealDetailErrorSchema },
|
|
982
971
|
],
|
|
983
972
|
},
|
|
984
973
|
},
|
|
@@ -7,7 +7,6 @@ import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
|
7
7
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
8
8
|
import { CustomerDeal, CustomerPipeline } from '../../../../data/entities'
|
|
9
9
|
import { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'
|
|
10
|
-
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
11
10
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
12
11
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
13
12
|
import { isOrganizationReadAccessAllowed } from '@open-mercato/core/modules/directory/utils/organizationScopeGuard'
|
|
@@ -24,10 +23,6 @@ function notFound(message: string) {
|
|
|
24
23
|
return NextResponse.json({ error: message }, { status: 404 })
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
function forbidden(message: string) {
|
|
28
|
-
return NextResponse.json({ error: message }, { status: 403 })
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
function badRequest(message: string, code?: string) {
|
|
32
27
|
return NextResponse.json(
|
|
33
28
|
code ? { error: message, code } : { error: message },
|
|
@@ -67,23 +62,10 @@ export async function GET(request: Request, context: { params?: Record<string, u
|
|
|
67
62
|
return NextResponse.json({ error: translate('customers.errors.authentication_required', 'Authentication required') }, { status: 401 })
|
|
68
63
|
}
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
rbac = null
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (!rbac || !auth?.sub) {
|
|
78
|
-
return forbidden(translate('customers.errors.access_denied', 'Access denied'))
|
|
79
|
-
}
|
|
80
|
-
const hasFeature = await rbac.userHasAllFeatures(auth.sub, ['customers.deals.view'], {
|
|
81
|
-
tenantId: auth.tenantId ?? null,
|
|
82
|
-
organizationId: auth.orgId ?? null,
|
|
83
|
-
})
|
|
84
|
-
if (!hasFeature) {
|
|
85
|
-
return forbidden(translate('customers.errors.access_denied', 'Access denied'))
|
|
86
|
-
}
|
|
65
|
+
// The API dispatcher already enforces `requireFeatures: ['customers.deals.view']`
|
|
66
|
+
// against the caller's effective (selected) organization before this handler
|
|
67
|
+
// runs, so no in-route feature re-check is needed. Re-checking against the token
|
|
68
|
+
// org (auth.orgId) would wrongly 403 org-switched callers (#5012).
|
|
87
69
|
|
|
88
70
|
const scope = await resolveOrganizationScopeForRequest({ container, auth, request })
|
|
89
71
|
const em = (container.resolve('em') as EntityManager)
|
|
@@ -98,8 +80,11 @@ export async function GET(request: Request, context: { params?: Record<string, u
|
|
|
98
80
|
return notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
99
81
|
}
|
|
100
82
|
|
|
83
|
+
// Existence oracle (#5504): deny a cross-org read as not-found — identical to
|
|
84
|
+
// the deal-not-found above — so it cannot reveal that a deal exists in an
|
|
85
|
+
// organization the caller cannot see.
|
|
101
86
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: deal.organizationId })) {
|
|
102
|
-
return
|
|
87
|
+
return notFound(translate('customers.errors.deal_not_found', 'Deal not found'))
|
|
103
88
|
}
|
|
104
89
|
|
|
105
90
|
if (!deal.closureOutcome) {
|
|
@@ -206,8 +191,8 @@ export const openApi: OpenApiRouteDoc = {
|
|
|
206
191
|
errors: [
|
|
207
192
|
{ status: 400, description: 'Deal is not closed', schema: dealStatsErrorSchema },
|
|
208
193
|
{ status: 401, description: 'Unauthorized', schema: dealStatsErrorSchema },
|
|
209
|
-
{ status: 403, description: 'Forbidden
|
|
210
|
-
{ status: 404, description: 'Deal not found', schema: dealStatsErrorSchema },
|
|
194
|
+
{ status: 403, description: 'Forbidden — caller lacks the required feature', schema: dealStatsErrorSchema },
|
|
195
|
+
{ status: 404, description: 'Deal not found, or its organization is not in the caller’s scope', schema: dealStatsErrorSchema },
|
|
211
196
|
],
|
|
212
197
|
},
|
|
213
198
|
},
|
|
@@ -11,9 +11,11 @@ import type { ExchangeRateService } from '@open-mercato/core/modules/currencies/
|
|
|
11
11
|
import { parseBooleanFromUnknown } from '@open-mercato/shared/lib/boolean'
|
|
12
12
|
import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
|
|
13
13
|
import type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'
|
|
14
|
+
import { readQueryParamList } from '@open-mercato/shared/lib/crud/query-params'
|
|
14
15
|
import { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'
|
|
15
16
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
16
17
|
import { fetchStuckDealIds } from '../../../lib/stuckDeals'
|
|
18
|
+
import { expandDealStatusAliases } from '../../../lib/dealStatus'
|
|
17
19
|
import { findMatchingEntityIdsBySearchTokensAcrossSources } from '../../utils'
|
|
18
20
|
import { E } from '#generated/entities.ids.generated'
|
|
19
21
|
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
@@ -27,7 +29,7 @@ export const metadata = {
|
|
|
27
29
|
const querySchema = z.object({
|
|
28
30
|
pipelineId: z.string().uuid().optional(),
|
|
29
31
|
search: z.string().optional(),
|
|
30
|
-
status: z.array(z.
|
|
32
|
+
status: z.array(z.string().max(50)).max(20).optional(),
|
|
31
33
|
ownerUserId: z.array(z.string().uuid()).optional(),
|
|
32
34
|
personId: z.array(z.string().uuid()).optional(),
|
|
33
35
|
companyId: z.array(z.string().uuid()).optional(),
|
|
@@ -121,11 +123,8 @@ export const openApi: OpenApiRouteDoc = {
|
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
function readArrayParam(searchParams: URLSearchParams, key: string): string[] | null {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
const flat = all.flatMap((v) => v.split(','))
|
|
127
|
-
const trimmed = flat.map((s) => s.trim()).filter(Boolean)
|
|
128
|
-
return trimmed.length ? trimmed : null
|
|
126
|
+
const values = readQueryParamList(searchParams, key)
|
|
127
|
+
return values.length ? values : null
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
function restrictToIds(where: string[], values: Array<string | number | null>, ids: string[]) {
|
|
@@ -247,9 +246,11 @@ export async function GET(req: Request) {
|
|
|
247
246
|
}
|
|
248
247
|
}
|
|
249
248
|
if (parsed.data.status && parsed.data.status.length) {
|
|
250
|
-
|
|
249
|
+
// Non-empty input always expands to a non-empty set, so this always narrows.
|
|
250
|
+
const expandedStatuses = expandDealStatusAliases(parsed.data.status)
|
|
251
|
+
const placeholders = expandedStatuses.map(() => '?').join(',')
|
|
251
252
|
where.push(`status IN (${placeholders})`)
|
|
252
|
-
values.push(...
|
|
253
|
+
values.push(...expandedStatuses)
|
|
253
254
|
}
|
|
254
255
|
if (parsed.data.ownerUserId && parsed.data.ownerUserId.length) {
|
|
255
256
|
const placeholders = parsed.data.ownerUserId.map(() => '?').join(',')
|
|
@@ -265,7 +266,14 @@ export async function GET(req: Request) {
|
|
|
265
266
|
values.push(parsed.data.expectedCloseAtTo)
|
|
266
267
|
}
|
|
267
268
|
if (parsed.data.isOverdue) {
|
|
268
|
-
|
|
269
|
+
// Mirror the list route's precedence: the caller-supplied status filter wins, and
|
|
270
|
+
// status='open' is injected only when none was provided.
|
|
271
|
+
const hasCallerStatus = !!parsed.data.status?.length
|
|
272
|
+
if (hasCallerStatus) {
|
|
273
|
+
where.push('expected_close_at < CURRENT_DATE')
|
|
274
|
+
} else {
|
|
275
|
+
where.push("expected_close_at < CURRENT_DATE AND status = 'open'")
|
|
276
|
+
}
|
|
269
277
|
}
|
|
270
278
|
if (parsed.data.isStuck) {
|
|
271
279
|
// Reuse the list endpoint's stuck-deal lookup so kanban headers, lane counts, and the
|
|
@@ -5,6 +5,7 @@ import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
|
5
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
6
6
|
import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
7
7
|
import type { CrudCtx } from '@open-mercato/shared/lib/crud/factory'
|
|
8
|
+
import { readQueryParamList } from '@open-mercato/shared/lib/crud/query-params'
|
|
8
9
|
import { SortDir, type QueryEngine } from '@open-mercato/shared/lib/query/types'
|
|
9
10
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
10
11
|
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
@@ -161,10 +162,8 @@ function toIsoStringOrNull(value: unknown): string | null {
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
function readArrayParam(searchParams: URLSearchParams, key: string): string[] | null {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
const trimmed = all.flatMap((value) => value.split(',')).map((value) => value.trim()).filter(Boolean)
|
|
167
|
-
return trimmed.length ? trimmed : null
|
|
165
|
+
const values = readQueryParamList(searchParams, key)
|
|
166
|
+
return values.length ? values : null
|
|
168
167
|
}
|
|
169
168
|
|
|
170
169
|
function collectRefIds(rows: unknown[], key: string): string[] {
|
|
@@ -545,5 +544,6 @@ export async function GET(req: Request) {
|
|
|
545
544
|
page: query.page,
|
|
546
545
|
pageSize: query.pageSize,
|
|
547
546
|
totalPages: Math.ceil(res.total / (query.pageSize || 1)),
|
|
547
|
+
...(res.meta?.listCountCapWarning ? { totalIsCapped: true } : {}),
|
|
548
548
|
})
|
|
549
549
|
}
|
|
@@ -22,7 +22,9 @@ import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
|
22
22
|
import { isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'
|
|
23
23
|
import { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'
|
|
24
24
|
import { consumeAdvancedFilterState, mergeAdvancedFilterTree } from '@open-mercato/shared/lib/crud/advanced-filter-integration'
|
|
25
|
+
import type { FilterGroup, FilterRule } from '@open-mercato/shared/lib/query/advanced-filter-tree'
|
|
25
26
|
import { fetchStuckDealIds } from '../../lib/stuckDeals'
|
|
27
|
+
import { expandDealStatusAliases } from '../../lib/dealStatus'
|
|
26
28
|
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
27
29
|
|
|
28
30
|
const logger = createLogger('customers')
|
|
@@ -31,6 +33,19 @@ const rawBodySchema = z.object({}).passthrough()
|
|
|
31
33
|
|
|
32
34
|
const stringOrStringArray = z.union([z.string(), z.array(z.string())])
|
|
33
35
|
const OPEN_DEAL_STATUSES = ['open', 'in_progress'] as const
|
|
36
|
+
// Tree operators whose `status` values are rewritten through the canonical vocabulary.
|
|
37
|
+
// Text (`contains`/`starts_with`/…) and range (`between`) operators are left untouched
|
|
38
|
+
// so a URL-supplied rule keeps its scalar semantics.
|
|
39
|
+
const STATUS_TREE_OPERATORS = new Set([
|
|
40
|
+
'is',
|
|
41
|
+
'equals',
|
|
42
|
+
'is_not',
|
|
43
|
+
'not_equals',
|
|
44
|
+
'is_any_of',
|
|
45
|
+
'has_any_of',
|
|
46
|
+
'is_none_of',
|
|
47
|
+
'has_none_of',
|
|
48
|
+
])
|
|
34
49
|
const booleanQueryParam = z.preprocess((value) => {
|
|
35
50
|
const parsed = parseBooleanFromUnknown(value)
|
|
36
51
|
return parsed === null ? value : parsed
|
|
@@ -245,6 +260,39 @@ function normalizeUuidList(values: Array<unknown>): string[] {
|
|
|
245
260
|
|
|
246
261
|
export async function buildDealListFilters(query: DealListQuery, ctx?: import('@open-mercato/shared/lib/crud/factory').CrudCtx) {
|
|
247
262
|
const advancedFilterTree = consumeAdvancedFilterState(query)
|
|
263
|
+
if (advancedFilterTree) {
|
|
264
|
+
// Expand status aliases in the advanced-filter tree so List (tree path) and
|
|
265
|
+
// Kanban (plain ?status=) share the same canonical vocabulary (#5107). Only
|
|
266
|
+
// set-membership operators are rewritten — text/range operators on `status`
|
|
267
|
+
// keep their pre-existing scalar semantics instead of being corrupted.
|
|
268
|
+
const walk = (node: FilterGroup | FilterRule): void => {
|
|
269
|
+
if (node.type === 'rule' && node.field === 'status' && STATUS_TREE_OPERATORS.has(node.operator)) {
|
|
270
|
+
const listOperators = new Set(['is_any_of', 'has_any_of', 'is_none_of', 'has_none_of'])
|
|
271
|
+
const rawValues: string[] = Array.isArray(node.value)
|
|
272
|
+
? (node.value as unknown[]).filter((v): v is string => typeof v === 'string')
|
|
273
|
+
: typeof node.value === 'string'
|
|
274
|
+
? [node.value]
|
|
275
|
+
: []
|
|
276
|
+
if (rawValues.length === 0) return
|
|
277
|
+
const expanded = expandDealStatusAliases(rawValues)
|
|
278
|
+
if (listOperators.has(node.operator)) {
|
|
279
|
+
node.value = expanded
|
|
280
|
+
} else if (expanded.length === 1) {
|
|
281
|
+
node.value = expanded[0]
|
|
282
|
+
} else {
|
|
283
|
+
node.value = expanded
|
|
284
|
+
if (node.operator === 'is' || node.operator === 'equals') {
|
|
285
|
+
node.operator = 'is_any_of'
|
|
286
|
+
} else if (node.operator === 'is_not' || node.operator === 'not_equals') {
|
|
287
|
+
node.operator = 'is_none_of'
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
} else if (node.type === 'group') {
|
|
291
|
+
for (const child of node.children) walk(child)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
walk(advancedFilterTree.root)
|
|
295
|
+
}
|
|
248
296
|
const filters: Record<string, unknown> = {}
|
|
249
297
|
let restrictedIds: string[] | null = null
|
|
250
298
|
|
|
@@ -300,7 +348,8 @@ export async function buildDealListFilters(query: DealListQuery, ctx?: import('@
|
|
|
300
348
|
}
|
|
301
349
|
}
|
|
302
350
|
|
|
303
|
-
const
|
|
351
|
+
const rawStatusList = query.status ? normalizeStringList(query.status) : []
|
|
352
|
+
const statusList = expandDealStatusAliases(rawStatusList)
|
|
304
353
|
if (statusList.length > 0) {
|
|
305
354
|
filters.status = statusList.length === 1 ? { $eq: statusList[0] } : { $in: statusList }
|
|
306
355
|
}
|
|
@@ -77,10 +77,14 @@ function ensureRouteOrganizationAccess(
|
|
|
77
77
|
organizationId: string,
|
|
78
78
|
scope: Awaited<ReturnType<typeof resolveCustomersRequestContext>>['scope'],
|
|
79
79
|
auth: Awaited<ReturnType<typeof resolveCustomersRequestContext>>['auth'],
|
|
80
|
-
|
|
80
|
+
notFoundMessage: string,
|
|
81
81
|
) {
|
|
82
|
+
// Existence oracle (#5504): a caller who holds the feature but whose scope
|
|
83
|
+
// excludes the record's organization is denied as not-found (the same response
|
|
84
|
+
// the caller gets for a missing record), so this cannot reveal that the record
|
|
85
|
+
// exists in an organization they cannot see.
|
|
82
86
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId })) {
|
|
83
|
-
throw
|
|
87
|
+
throw notFound(notFoundMessage)
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
|
|
@@ -132,7 +136,7 @@ async function resolveEntityRouteScope(
|
|
|
132
136
|
if (!entity || entity.tenantId !== auth.tenantId) {
|
|
133
137
|
throw notFound(translate('customers.errors.customer_not_found', 'Customer not found'))
|
|
134
138
|
}
|
|
135
|
-
ensureRouteOrganizationAccess(entity.organizationId, scope, auth, translate)
|
|
139
|
+
ensureRouteOrganizationAccess(entity.organizationId, scope, auth, translate('customers.errors.customer_not_found', 'Customer not found'))
|
|
136
140
|
return {
|
|
137
141
|
entity,
|
|
138
142
|
organizationId: entity.organizationId,
|
|
@@ -164,7 +168,7 @@ async function resolveRoleRouteScope(
|
|
|
164
168
|
) {
|
|
165
169
|
throw notFound(translate('customers.errors.role_not_found', 'Role not found'))
|
|
166
170
|
}
|
|
167
|
-
ensureRouteOrganizationAccess(role.organizationId, scope, auth, translate)
|
|
171
|
+
ensureRouteOrganizationAccess(role.organizationId, scope, auth, translate('customers.errors.role_not_found', 'Role not found'))
|
|
168
172
|
return {
|
|
169
173
|
role,
|
|
170
174
|
organizationId: role.organizationId,
|
|
@@ -180,7 +180,7 @@ type InteractionListRow = {
|
|
|
180
180
|
all_day: boolean | null
|
|
181
181
|
recurrence_rule: string | null
|
|
182
182
|
recurrence_end: Date | null
|
|
183
|
-
participants: Array<{ userId
|
|
183
|
+
participants: Array<{ userId?: string; name?: string; email?: string; status?: string }> | null
|
|
184
184
|
reminder_minutes: number | null
|
|
185
185
|
visibility: string | null
|
|
186
186
|
linked_entities: Array<{ id: string; type: string; label: string }> | null
|
|
@@ -744,7 +744,13 @@ const interactionListItemSchema = z
|
|
|
744
744
|
recurrenceEnd: z.string().nullable().optional(),
|
|
745
745
|
participants: z.array(
|
|
746
746
|
z.object({
|
|
747
|
-
userId: z
|
|
747
|
+
userId: z
|
|
748
|
+
.string()
|
|
749
|
+
.uuid()
|
|
750
|
+
.optional()
|
|
751
|
+
.describe(
|
|
752
|
+
'Absent for an external guest, who has no person/customer/staff record and is identified by email instead. Identify a participant by userId when present, otherwise by its normalized email.',
|
|
753
|
+
),
|
|
748
754
|
name: z.string().optional(),
|
|
749
755
|
email: z.string().optional(),
|
|
750
756
|
status: z.string().optional(),
|
|
@@ -3,6 +3,7 @@ import { z } from 'zod'
|
|
|
3
3
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
4
4
|
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
5
|
import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
6
|
+
import { isUnrestrictedOrganizationScope } from '@open-mercato/shared/lib/auth/organizationAccess'
|
|
6
7
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
8
|
import type { QueryEngine } from '@open-mercato/shared/lib/query/types'
|
|
8
9
|
import { createCustomersCrudOpenApi, createPagedListResponseSchema } from '../../openapi'
|
|
@@ -40,11 +41,30 @@ const MERGED_TASK_FETCH_CAP = 2000
|
|
|
40
41
|
export async function GET(request: Request): Promise<Response> {
|
|
41
42
|
const { translate } = await resolveTranslations()
|
|
42
43
|
try {
|
|
43
|
-
const { auth, em, organizationIds, container, selectedOrganizationId } =
|
|
44
|
+
const { auth, em, organizationIds, container, selectedOrganizationId, scope } =
|
|
44
45
|
await resolveCustomersRequestContext(request)
|
|
45
46
|
const query = querySchema.parse(Object.fromEntries(new URL(request.url).searchParams))
|
|
46
47
|
const flags = await resolveCustomerInteractionFeatureFlags(container, auth.tenantId)
|
|
47
48
|
const exportAll = parseBooleanToken(query.all) === true
|
|
49
|
+
const isUnrestricted = isUnrestrictedOrganizationScope({
|
|
50
|
+
isSuperAdmin: auth.isSuperAdmin === true,
|
|
51
|
+
allowedOrganizationIds: scope?.allowedIds,
|
|
52
|
+
})
|
|
53
|
+
if (!isUnrestricted && (!organizationIds || organizationIds.length === 0)) {
|
|
54
|
+
logger.warn('customers.interactions.tasks.list collapsed organization scope', {
|
|
55
|
+
tenantId: auth.tenantId,
|
|
56
|
+
organizationIds,
|
|
57
|
+
selectedId: scope?.selectedId ?? null,
|
|
58
|
+
allowedIdsCount: scope?.allowedIds?.length ?? null,
|
|
59
|
+
})
|
|
60
|
+
return NextResponse.json({
|
|
61
|
+
items: [],
|
|
62
|
+
total: 0,
|
|
63
|
+
page: exportAll ? 1 : query.page,
|
|
64
|
+
pageSize: exportAll ? 0 : query.pageSize,
|
|
65
|
+
totalPages: 1,
|
|
66
|
+
})
|
|
67
|
+
}
|
|
48
68
|
const search = normalizeTodoSearch(query.search)
|
|
49
69
|
const queryEngine = container.resolve('queryEngine') as QueryEngine
|
|
50
70
|
|
|
@@ -59,6 +79,7 @@ export async function GET(request: Request): Promise<Response> {
|
|
|
59
79
|
entityId: query.entityId,
|
|
60
80
|
pagination: exportAll ? null : { page: query.page, pageSize: query.pageSize },
|
|
61
81
|
searchText: search,
|
|
82
|
+
isUnrestricted,
|
|
62
83
|
},
|
|
63
84
|
)
|
|
64
85
|
const total = canonical.total
|
|
@@ -80,6 +101,7 @@ export async function GET(request: Request): Promise<Response> {
|
|
|
80
101
|
const [legacyRows, canonicalRows] = await Promise.all([
|
|
81
102
|
listLegacyTodoRows(em, queryEngine, auth.tenantId, organizationIds, query.entityId, {
|
|
82
103
|
limit: legacyWindow,
|
|
104
|
+
isUnrestricted,
|
|
83
105
|
}),
|
|
84
106
|
listCanonicalTodoRows(
|
|
85
107
|
em,
|
|
@@ -91,6 +113,7 @@ export async function GET(request: Request): Promise<Response> {
|
|
|
91
113
|
entityId: query.entityId,
|
|
92
114
|
includeDeleted: true,
|
|
93
115
|
limit: legacyWindow,
|
|
116
|
+
isUnrestricted,
|
|
94
117
|
},
|
|
95
118
|
),
|
|
96
119
|
])
|
|
@@ -234,7 +234,7 @@ export async function DELETE(req: Request, ctx: { params?: { id?: string; linkId
|
|
|
234
234
|
const { translate } = await resolveTranslations()
|
|
235
235
|
try {
|
|
236
236
|
const { id, linkId } = paramsSchema.parse({ id: ctx.params?.id, linkId: ctx.params?.linkId })
|
|
237
|
-
const { container, auth, selectedOrganizationId, person } = await loadPersonContext(req, id)
|
|
237
|
+
const { container, auth, selectedOrganizationId, person, profile } = await loadPersonContext(req, id)
|
|
238
238
|
if (!selectedOrganizationId) {
|
|
239
239
|
throw new CrudHttpError(400, { error: translate('customers.errors.organization_required', 'Organization context is required') })
|
|
240
240
|
}
|
|
@@ -262,18 +262,26 @@ export async function DELETE(req: Request, ctx: { params?: { id?: string; linkId
|
|
|
262
262
|
auth.tenantId,
|
|
263
263
|
selectedOrganizationId,
|
|
264
264
|
)
|
|
265
|
-
|
|
265
|
+
// No `CustomerPersonCompanyLink` row resolves for the profile-only association case
|
|
266
|
+
// (`CustomerPersonProfile.company` set without a link row, e.g. from a CRM migration).
|
|
267
|
+
// The delete command accepts that shape too, so it is dispatched instead of 404ing and
|
|
268
|
+
// the detach keeps its audit entry, undo token and cache invalidation (#5114).
|
|
269
|
+
const isProfileOnlyMatch =
|
|
270
|
+
profile.company && typeof profile.company !== 'string' && profile.company.id === linkId
|
|
271
|
+
if (!resolvedLinkId && !isProfileOnlyMatch) {
|
|
266
272
|
throw notFound(translate('customers.errors.person_company_link_not_found', 'Person-company link not found'))
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
const commandInput = personCompanyLinkDeleteSchema.parse({
|
|
270
|
-
|
|
276
|
+
...(resolvedLinkId
|
|
277
|
+
? { linkId: resolvedLinkId }
|
|
278
|
+
: { personEntityId: person.id, companyEntityId: linkId }),
|
|
271
279
|
tenantId: auth.tenantId,
|
|
272
280
|
organizationId: selectedOrganizationId,
|
|
273
281
|
} satisfies PersonCompanyLinkDeleteInput)
|
|
274
282
|
|
|
275
283
|
const commandBus = container.resolve('commandBus') as CommandBus
|
|
276
|
-
const { result, logEntry } = await commandBus.execute<PersonCompanyLinkDeleteInput, { linkId: string }>(
|
|
284
|
+
const { result, logEntry } = await commandBus.execute<PersonCompanyLinkDeleteInput, { linkId: string | null }>(
|
|
277
285
|
'customers.personCompanyLinks.delete',
|
|
278
286
|
{
|
|
279
287
|
input: commandInput,
|
|
@@ -38,8 +38,11 @@ export async function loadPersonContext(req: Request, personId: string) {
|
|
|
38
38
|
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// Existence oracle (#5504): deny a cross-org read as not-found — identical to
|
|
42
|
+
// the parent-not-found above — so it cannot reveal that a person exists in an
|
|
43
|
+
// organization the caller cannot see.
|
|
41
44
|
if (!isOrganizationReadAccessAllowed({ scope, auth: authenticatedAuth, organizationId: person.organizationId })) {
|
|
42
|
-
throw
|
|
45
|
+
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
const profile = await findOneWithDecryption(
|
|
@@ -178,8 +178,11 @@ export async function GET(req: Request, ctx: { params?: { id?: string } }) {
|
|
|
178
178
|
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
// Existence oracle (#5504): deny a cross-org read as not-found — identical to
|
|
182
|
+
// the parent-not-found above — so it cannot reveal that a person exists in an
|
|
183
|
+
// organization the caller cannot see.
|
|
181
184
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: person.organizationId })) {
|
|
182
|
-
throw
|
|
185
|
+
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
183
186
|
}
|
|
184
187
|
|
|
185
188
|
const entityScope = { tenantId: auth.tenantId, organizationId: person.organizationId }
|