@open-mercato/core 0.7.0 → 0.7.1-develop.7102.1.b41f7e3e51
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/dist/helpers/integration/api.js +13 -1
- package/dist/helpers/integration/api.js.map +2 -2
- package/dist/helpers/integration/communicationChannelsFixtures.js +19 -0
- package/dist/helpers/integration/communicationChannelsFixtures.js.map +2 -2
- package/dist/modules/api_keys/api/keys/route.js +1 -1
- package/dist/modules/api_keys/api/keys/route.js.map +2 -2
- package/dist/modules/api_keys/backend/api-keys/page.js +3 -1
- package/dist/modules/api_keys/backend/api-keys/page.js.map +2 -2
- package/dist/modules/api_keys/di.js +9 -0
- package/dist/modules/api_keys/di.js.map +7 -0
- package/dist/modules/api_keys/services/principalService.js +31 -0
- package/dist/modules/api_keys/services/principalService.js.map +7 -0
- package/dist/modules/attachments/api/route.js +2 -2
- package/dist/modules/attachments/api/route.js.map +2 -2
- package/dist/modules/attachments/components/AttachmentLibrary.js +2 -0
- package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
- package/dist/modules/attachments/di.js +11 -1
- package/dist/modules/attachments/di.js.map +2 -2
- package/dist/modules/attachments/index.js.map +1 -1
- package/dist/modules/attachments/lib/attachment-service.js +313 -0
- package/dist/modules/attachments/lib/attachment-service.js.map +7 -0
- package/dist/modules/attachments/lib/scoped-upload-service.js +15 -2
- package/dist/modules/attachments/lib/scoped-upload-service.js.map +2 -2
- package/dist/modules/attachments/lib/upload-limits.js +6 -2
- package/dist/modules/attachments/lib/upload-limits.js.map +2 -2
- package/dist/modules/audit_logs/backend/audit-logs/page.js +6 -0
- package/dist/modules/audit_logs/backend/audit-logs/page.js.map +2 -2
- package/dist/modules/audit_logs/lib/display-helpers.js +19 -11
- package/dist/modules/audit_logs/lib/display-helpers.js.map +2 -2
- package/dist/modules/audit_logs/services/actionLogService.js +57 -12
- package/dist/modules/audit_logs/services/actionLogService.js.map +3 -3
- package/dist/modules/auth/acl.js +30 -5
- package/dist/modules/auth/acl.js.map +2 -2
- package/dist/modules/auth/api/feature-check.js +8 -2
- package/dist/modules/auth/api/feature-check.js.map +2 -2
- package/dist/modules/auth/api/login.js +4 -1
- package/dist/modules/auth/api/login.js.map +2 -2
- package/dist/modules/auth/api/reset/validate.js +55 -0
- package/dist/modules/auth/api/reset/validate.js.map +7 -0
- package/dist/modules/auth/api/roles/acl/route.js +28 -33
- package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
- package/dist/modules/auth/api/session/refresh.js +25 -1
- package/dist/modules/auth/api/session/refresh.js.map +2 -2
- package/dist/modules/auth/api/users/acl/route.js +96 -51
- package/dist/modules/auth/api/users/acl/route.js.map +2 -2
- package/dist/modules/auth/api/users/route.js +13 -5
- package/dist/modules/auth/api/users/route.js.map +2 -2
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/roles/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/roles/page.js +3 -1
- package/dist/modules/auth/backend/roles/page.js.map +2 -2
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js +5 -1
- package/dist/modules/auth/backend/users/[id]/edit/page.meta.js.map +2 -2
- package/dist/modules/auth/backend/users/page.js +2 -1
- package/dist/modules/auth/backend/users/page.js.map +2 -2
- package/dist/modules/auth/commands/acl.js +254 -0
- package/dist/modules/auth/commands/acl.js.map +7 -0
- package/dist/modules/auth/components/AclEditor.js +39 -30
- package/dist/modules/auth/components/AclEditor.js.map +2 -2
- package/dist/modules/auth/data/entities.js.map +2 -2
- package/dist/modules/auth/data/validators.js +5 -1
- package/dist/modules/auth/data/validators.js.map +2 -2
- package/dist/modules/auth/di.js +35 -9
- package/dist/modules/auth/di.js.map +2 -2
- package/dist/modules/auth/frontend/reset/[token]/page.js +46 -0
- package/dist/modules/auth/frontend/reset/[token]/page.js.map +2 -2
- package/dist/modules/auth/lib/grantChecks.js.map +2 -2
- package/dist/modules/auth/lib/userIdFilter.js +16 -0
- package/dist/modules/auth/lib/userIdFilter.js.map +7 -0
- package/dist/modules/auth/services/authService.js +16 -2
- package/dist/modules/auth/services/authService.js.map +2 -2
- package/dist/modules/auth/services/principalService.js +200 -0
- package/dist/modules/auth/services/principalService.js.map +7 -0
- package/dist/modules/auth/services/rbacService.js +67 -24
- package/dist/modules/auth/services/rbacService.js.map +3 -3
- package/dist/modules/auth/services/roleOrganizationScope.js +41 -0
- package/dist/modules/auth/services/roleOrganizationScope.js.map +7 -0
- package/dist/modules/business_rules/backend/logs/page.js +3 -1
- package/dist/modules/business_rules/backend/logs/page.js.map +2 -2
- package/dist/modules/business_rules/backend/rules/page.js +3 -1
- package/dist/modules/business_rules/backend/rules/page.js.map +2 -2
- package/dist/modules/business_rules/backend/sets/page.js +3 -1
- package/dist/modules/business_rules/backend/sets/page.js.map +2 -2
- package/dist/modules/business_rules/lib/expression-evaluator.js +9 -9
- package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
- package/dist/modules/business_rules/lib/rule-evaluator.js +10 -9
- package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
- package/dist/modules/catalog/ai-agents.js +1 -1
- package/dist/modules/catalog/ai-agents.js.map +1 -1
- package/dist/modules/catalog/ai-tools/merchandising-pack.js +2 -2
- package/dist/modules/catalog/ai-tools/merchandising-pack.js.map +2 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js +5 -2
- package/dist/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.js.map +2 -2
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js +2 -0
- package/dist/modules/catalog/components/categories/CategoriesDataTable.js.map +2 -2
- package/dist/modules/catalog/components/products/ProductsDataTable.js +7 -1
- package/dist/modules/catalog/components/products/ProductsDataTable.js.map +2 -2
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js +2 -0
- package/dist/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.js.map +2 -2
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js +9 -1
- package/dist/modules/communication_channels/api/post/channels/[id]/test-send/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/test-seed/route.js +95 -10
- package/dist/modules/communication_channels/api/post/test-seed/route.js.map +2 -2
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js +3 -0
- package/dist/modules/communication_channels/backend/communication_channels/channels/page.js.map +2 -2
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js +14 -1
- package/dist/modules/communication_channels/commands/ingest-inbound-message.js.map +2 -2
- package/dist/modules/communication_channels/di.js +7 -1
- package/dist/modules/communication_channels/di.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-capabilities.js +4 -1
- package/dist/modules/communication_channels/lib/email-capabilities.js.map +2 -2
- package/dist/modules/communication_channels/lib/outbound-recipient.js +33 -0
- package/dist/modules/communication_channels/lib/outbound-recipient.js.map +7 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js +51 -0
- package/dist/modules/communication_channels/lib/resolve-channel-type.js.map +7 -0
- package/dist/modules/communication_channels/lib/test-seed.js +41 -2
- package/dist/modules/communication_channels/lib/test-seed.js.map +2 -2
- package/dist/modules/configs/lib/system-status.js +9 -0
- package/dist/modules/configs/lib/system-status.js.map +2 -2
- package/dist/modules/currencies/backend/currencies/page.js +3 -1
- package/dist/modules/currencies/backend/currencies/page.js.map +2 -2
- package/dist/modules/currencies/backend/exchange-rates/page.js +3 -1
- package/dist/modules/currencies/backend/exchange-rates/page.js.map +2 -2
- package/dist/modules/currencies/services/rateFetchingService.js +6 -1
- package/dist/modules/currencies/services/rateFetchingService.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js +9 -0
- package/dist/modules/customer_accounts/api/admin/domain-mappings.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/roles/page.js.map +2 -2
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js +3 -1
- package/dist/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.js.map +2 -2
- package/dist/modules/customer_accounts/services/domainMappingService.js +10 -0
- package/dist/modules/customer_accounts/services/domainMappingService.js.map +2 -2
- package/dist/modules/customers/ai-tools/companies-pack.js +4 -1
- package/dist/modules/customers/ai-tools/companies-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js +13 -2
- package/dist/modules/customers/ai-tools/deal-analyzer-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/deals-pack.js +52 -6
- package/dist/modules/customers/ai-tools/deals-pack.js.map +2 -2
- package/dist/modules/customers/ai-tools/people-pack.js +4 -1
- package/dist/modules/customers/ai-tools/people-pack.js.map +2 -2
- package/dist/modules/customers/api/activities/route.js +48 -6
- package/dist/modules/customers/api/activities/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +20 -64
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/route.js +17 -94
- package/dist/modules/customers/api/companies/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js +8 -5
- package/dist/modules/customers/api/dashboard/widgets/customer-todos/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +1 -1
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +8 -25
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/stats/route.js +3 -22
- package/dist/modules/customers/api/deals/[id]/stats/route.js.map +2 -2
- package/dist/modules/customers/api/deals/aggregate/route.js +11 -4
- package/dist/modules/customers/api/deals/aggregate/route.js.map +2 -2
- package/dist/modules/customers/api/deals/map/route.js +2 -1
- package/dist/modules/customers/api/deals/map/route.js.map +2 -2
- package/dist/modules/customers/api/deals/route.js +38 -1
- package/dist/modules/customers/api/deals/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +4 -4
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/interactions/route.js +3 -1
- package/dist/modules/customers/api/interactions/route.js.map +2 -2
- package/dist/modules/customers/api/interactions/tasks/route.js +27 -4
- package/dist/modules/customers/api/interactions/tasks/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +4 -3
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +1 -1
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/route.js +11 -10
- package/dist/modules/customers/api/people/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/people/check-phone/route.js +51 -9
- package/dist/modules/customers/api/people/check-phone/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +30 -5
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/page.js +4 -2
- package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +6 -1
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/page.js +5 -2
- package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js +4 -13
- package/dist/modules/customers/backend/customers/deals/pipeline/components/Lane.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js +85 -14
- package/dist/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js +18 -0
- package/dist/modules/customers/backend/customers/deals/pipeline/components/toneClasses.js.map +7 -0
- package/dist/modules/customers/backend/customers/people/page.js +4 -2
- package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js +9 -3
- package/dist/modules/customers/backend/hooks/useEmailDuplicateCheck.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +21 -34
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js.map +1 -1
- package/dist/modules/customers/commands/personCompanyLinks.js +131 -2
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/components/CustomerTodosTable.js +1 -0
- package/dist/modules/customers/components/CustomerTodosTable.js.map +2 -2
- package/dist/modules/customers/components/DealsKpiStrip.js +7 -6
- package/dist/modules/customers/components/DealsKpiStrip.js.map +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js +2 -2
- package/dist/modules/customers/components/calendar/AgendaList.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarScreen.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarScreen.js.map +2 -2
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js +1 -1
- package/dist/modules/customers/components/calendar/CalendarSettingsModal.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventBlock.js +1 -1
- package/dist/modules/customers/components/calendar/EventBlock.js.map +2 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js +3 -2
- package/dist/modules/customers/components/calendar/EventPeekPopover.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/PeopleField.js +40 -5
- package/dist/modules/customers/components/calendar/editor/PeopleField.js.map +2 -2
- package/dist/modules/customers/components/calendar/editor/hooks.js +2 -1
- package/dist/modules/customers/components/calendar/editor/hooks.js.map +2 -2
- package/dist/modules/customers/components/calendar/types.js +1 -1
- package/dist/modules/customers/components/calendar/types.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyKpiBar.js +5 -4
- package/dist/modules/customers/components/detail/CompanyKpiBar.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js +3 -1
- package/dist/modules/customers/components/detail/CompanyPeopleSection.js.map +2 -2
- package/dist/modules/customers/components/detail/DealForm.js +19 -7
- package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
- package/dist/modules/customers/components/detail/DealsSection.js +6 -5
- package/dist/modules/customers/components/detail/DealsSection.js.map +2 -2
- package/dist/modules/customers/components/detail/EntityTagsDialog.js +35 -11
- package/dist/modules/customers/components/detail/EntityTagsDialog.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js +3 -1
- package/dist/modules/customers/components/detail/PersonCompaniesSection.js.map +2 -2
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js +19 -13
- package/dist/modules/customers/components/detail/hooks/usePersonTasks.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js +4 -4
- package/dist/modules/customers/components/detail/schedule/ParticipantsField.js.map +2 -2
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +3 -3
- package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
- package/dist/modules/customers/components/detail/utils.js +5 -5
- package/dist/modules/customers/components/detail/utils.js.map +2 -2
- package/dist/modules/customers/data/entities.js.map +1 -1
- package/dist/modules/customers/data/validators.js +32 -3
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/events.js +5 -0
- package/dist/modules/customers/events.js.map +2 -2
- package/dist/modules/customers/lib/calendar/conflicts.js +8 -2
- package/dist/modules/customers/lib/calendar/conflicts.js.map +2 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js +3 -2
- package/dist/modules/customers/lib/calendar/editorPayload.js.map +2 -2
- package/dist/modules/customers/lib/calendar/mapItem.js +8 -3
- package/dist/modules/customers/lib/calendar/mapItem.js.map +2 -2
- package/dist/modules/customers/lib/calendar/participantIdentity.js +9 -0
- package/dist/modules/customers/lib/calendar/participantIdentity.js.map +7 -0
- package/dist/modules/customers/lib/closureStage.js +45 -0
- package/dist/modules/customers/lib/closureStage.js.map +7 -0
- package/dist/modules/customers/lib/dealStatus.js +30 -0
- package/dist/modules/customers/lib/dealStatus.js.map +2 -2
- package/dist/modules/customers/lib/detailReadAccess.js +12 -0
- package/dist/modules/customers/lib/detailReadAccess.js.map +7 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js +1 -0
- package/dist/modules/customers/lib/findPeopleByAddresses.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +100 -2
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +12 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/dashboards/lib/widgetScope.js +6 -1
- package/dist/modules/dashboards/lib/widgetScope.js.map +2 -2
- package/dist/modules/data_sync/backend/data-sync/page.js +3 -1
- package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
- package/dist/modules/data_sync/lib/abandoned-run.js +19 -0
- package/dist/modules/data_sync/lib/abandoned-run.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-engine.js +72 -6
- package/dist/modules/data_sync/lib/sync-engine.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-export.js +5 -1
- package/dist/modules/data_sync/workers/sync-export.js.map +2 -2
- package/dist/modules/data_sync/workers/sync-import.js +5 -1
- package/dist/modules/data_sync/workers/sync-import.js.map +2 -2
- package/dist/modules/devices/acl.js +9 -1
- package/dist/modules/devices/acl.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/[id]/route.js +5 -32
- package/dist/modules/devices/api/admin/devices/[id]/route.js.map +2 -2
- package/dist/modules/devices/api/admin/devices/route.js +14 -1
- package/dist/modules/devices/api/admin/devices/route.js.map +2 -2
- package/dist/modules/devices/api/deviceList.js +99 -12
- package/dist/modules/devices/api/deviceList.js.map +2 -2
- package/dist/modules/devices/api/deviceSerialization.js +46 -0
- package/dist/modules/devices/api/deviceSerialization.js.map +7 -0
- package/dist/modules/devices/api/openapi.js +3 -1
- package/dist/modules/devices/api/openapi.js.map +2 -2
- package/dist/modules/devices/api/route.js +9 -1
- package/dist/modules/devices/api/route.js.map +2 -2
- package/dist/modules/devices/backend/devices/[id]/page.js +10 -26
- package/dist/modules/devices/backend/devices/[id]/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/create/page.js +17 -1
- package/dist/modules/devices/backend/devices/create/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/page.js +28 -34
- package/dist/modules/devices/backend/devices/page.js.map +2 -2
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js +34 -0
- package/dist/modules/devices/backend/devices/useDeviceUserLabels.js.map +7 -0
- package/dist/modules/devices/backend/devices/userOptions.js +52 -0
- package/dist/modules/devices/backend/devices/userOptions.js.map +7 -0
- package/dist/modules/devices/setup.js +6 -2
- package/dist/modules/devices/setup.js.map +2 -2
- package/dist/modules/directory/backend/directory/organizations/page.js +2 -1
- package/dist/modules/directory/backend/directory/organizations/page.js.map +2 -2
- package/dist/modules/directory/backend/directory/tenants/page.js +2 -1
- package/dist/modules/directory/backend/directory/tenants/page.js.map +2 -2
- package/dist/modules/directory/di.js +9 -0
- package/dist/modules/directory/di.js.map +2 -2
- package/dist/modules/directory/services/organizationHierarchyService.js +29 -0
- package/dist/modules/directory/services/organizationHierarchyService.js.map +7 -0
- package/dist/modules/directory/services/organizationScopeService.js +56 -0
- package/dist/modules/directory/services/organizationScopeService.js.map +7 -0
- package/dist/modules/directory/utils/organizationScope.js.map +2 -2
- package/dist/modules/entities/api/records.js +4 -2
- package/dist/modules/entities/api/records.js.map +2 -2
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js +3 -1
- package/dist/modules/entities/backend/entities/user/[entityId]/records/page.js.map +2 -2
- package/dist/modules/eudr/api/plots/route.js +5 -1
- package/dist/modules/eudr/api/plots/route.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/evidence-submissions/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/plots/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/plots/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/product-mappings/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/risk-assessments/page.js.map +2 -2
- package/dist/modules/eudr/backend/eudr/statements/page.js +3 -0
- package/dist/modules/eudr/backend/eudr/statements/page.js.map +2 -2
- package/dist/modules/eudr/commands/statements.js +0 -3
- package/dist/modules/eudr/commands/statements.js.map +2 -2
- package/dist/modules/eudr/data/validators.js +4 -1
- package/dist/modules/eudr/data/validators.js.map +2 -2
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js +1 -0
- package/dist/modules/feature_toggles/components/FeatureTogglesTable.js.map +2 -2
- package/dist/modules/feature_toggles/components/OverridesTable.js +1 -0
- package/dist/modules/feature_toggles/components/OverridesTable.js.map +2 -2
- package/dist/modules/feature_toggles/defaults.json +0 -8
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js +3 -0
- package/dist/modules/inbox_ops/backend/inbox-ops/page.js.map +2 -2
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js +1 -12
- package/dist/modules/inbox_ops/lib/htmlToPlainText.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +6 -1
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/[id]/page.js +38 -29
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +36 -9
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js +55 -0
- package/dist/modules/integrations/backend/integrations/credential-secret-fields.js.map +7 -0
- package/dist/modules/integrations/data/validators.js +11 -3
- package/dist/modules/integrations/data/validators.js.map +2 -2
- package/dist/modules/integrations/lib/credentials-masking.js +6 -2
- package/dist/modules/integrations/lib/credentials-masking.js.map +2 -2
- package/dist/modules/messages/api/[id]/route.js +29 -1
- package/dist/modules/messages/api/[id]/route.js.map +2 -2
- package/dist/modules/messages/api/openapi.js +17 -2
- package/dist/modules/messages/api/openapi.js.map +2 -2
- package/dist/modules/messages/api/route.js +17 -2
- package/dist/modules/messages/api/route.js.map +2 -2
- package/dist/modules/messages/components/MessagesInboxPageClient.js +7 -14
- package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
- package/dist/modules/messages/components/inboxFilters.js +15 -0
- package/dist/modules/messages/components/inboxFilters.js.map +2 -2
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js +11 -1
- package/dist/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js +3 -1
- package/dist/modules/messages/components/message-detail/panels/MessageHeader.js.map +2 -2
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js +2 -1
- package/dist/modules/messages/components/message-detail/panels/thread-panel.js.map +2 -2
- package/dist/modules/messages/components/messageListLabels.js +14 -2
- package/dist/modules/messages/components/messageListLabels.js.map +2 -2
- package/dist/modules/messages/data/validators.js +18 -4
- package/dist/modules/messages/data/validators.js.map +2 -2
- package/dist/modules/messages/lib/channel-sender-identity.js +26 -0
- package/dist/modules/messages/lib/channel-sender-identity.js.map +7 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js +41 -0
- package/dist/modules/messages/lib/composeSourceChannelType.js.map +7 -0
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +4 -6
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js +3 -1
- package/dist/modules/payment_gateways/backend/payment-gateways/page.js.map +2 -2
- package/dist/modules/payment_gateways/lib/webhook-processor.js +7 -0
- package/dist/modules/payment_gateways/lib/webhook-processor.js.map +2 -2
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -0
- package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/page.js +3 -1
- package/dist/modules/push_notifications/backend/push_notifications/page.js.map +2 -2
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js +1 -1
- package/dist/modules/push_notifications/backend/push_notifications/send/page.js.map +2 -2
- package/dist/modules/query_index/lib/engine.js +150 -51
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-entity-policy.js +14 -0
- package/dist/modules/query_index/lib/search-entity-policy.js.map +7 -0
- package/dist/modules/query_index/lib/search-tokens.js +79 -3
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/resources/backend/resources/resource-types/page.js +3 -1
- package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
- package/dist/modules/resources/backend/resources/resources/page.js +3 -1
- package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/offers/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/offers/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/channels/page.js +3 -0
- package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
- package/dist/modules/sales/backend/sales/documents/[id]/page.js +10 -8
- package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +79 -1
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/components/PriceWithCurrency.js +7 -5
- package/dist/modules/sales/components/PriceWithCurrency.js.map +2 -2
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js +3 -0
- package/dist/modules/sales/components/channels/SalesChannelOffersPanel.js.map +2 -2
- package/dist/modules/sales/components/documents/AdjustmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/AdjustmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ItemsSection.js +51 -22
- package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/LineItemDialog.js +83 -18
- package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/PaymentsSection.js +23 -9
- package/dist/modules/sales/components/documents/PaymentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/ReturnsSection.js +8 -6
- package/dist/modules/sales/components/documents/ReturnsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js +68 -14
- package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js +6 -5
- package/dist/modules/sales/components/documents/SalesOrderDraftLines.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentDialog.js +5 -4
- package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
- package/dist/modules/sales/components/documents/ShipmentsSection.js +8 -6
- package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js +54 -0
- package/dist/modules/sales/components/documents/lineItemShipmentLock.js.map +7 -0
- package/dist/modules/sales/components/documents/lineItemUtils.js +2 -2
- package/dist/modules/sales/components/documents/lineItemUtils.js.map +2 -2
- package/dist/modules/sales/data/entities.js +8 -2
- package/dist/modules/sales/data/entities.js.map +2 -2
- package/dist/modules/sales/extension-points.js +1 -0
- package/dist/modules/sales/extension-points.js.map +2 -2
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js +33 -0
- package/dist/modules/sales/lib/salesChannelsToggleSeed.js.map +7 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js +32 -0
- package/dist/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.js.map +7 -0
- package/dist/modules/sales/setup.js +2 -0
- package/dist/modules/sales/setup.js.map +2 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js +10 -2
- package/dist/modules/sales/widgets/injection/payment-gateway-status-column/widget.js.map +2 -2
- package/dist/modules/sales/widgets/injection-table.js +4 -7
- package/dist/modules/sales/widgets/injection-table.js.map +2 -2
- package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -0
- package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-members/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/team-roles/page.js +3 -0
- package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/teams/page.js +3 -0
- package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/page.js +29 -18
- package/dist/modules/staff/backend/staff/timesheets/page.js.map +2 -2
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js +3 -0
- package/dist/modules/staff/backend/staff/timesheets/projects/page.js.map +2 -2
- package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
- package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
- package/dist/modules/warranty_claims/api/assignees/route.js +3 -3
- package/dist/modules/warranty_claims/api/assignees/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js +2 -2
- package/dist/modules/warranty_claims/api/portal/attachments/route.js.map +2 -2
- package/dist/modules/warranty_claims/api/portal/claims/route.js +12 -9
- package/dist/modules/warranty_claims/api/portal/claims/route.js.map +2 -2
- package/dist/modules/warranty_claims/backend/page.js +3 -0
- package/dist/modules/warranty_claims/backend/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/registrations/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.js.map +2 -2
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js +3 -0
- package/dist/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.js.map +2 -2
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js +3 -0
- package/dist/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.js.map +2 -2
- package/dist/modules/wms/api/warehouseSearch.js +21 -0
- package/dist/modules/wms/api/warehouseSearch.js.map +7 -0
- package/dist/modules/wms/api/warehouses/route.js +13 -9
- package/dist/modules/wms/api/warehouses/route.js.map +2 -2
- package/dist/modules/wms/api/zones/route.js +15 -2
- package/dist/modules/wms/api/zones/route.js.map +2 -2
- package/dist/modules/wms/commands/configuration.js +121 -9
- package/dist/modules/wms/commands/configuration.js.map +2 -2
- package/dist/modules/wms/commands/inventory-actions.js +3 -0
- package/dist/modules/wms/commands/inventory-actions.js.map +2 -2
- package/dist/modules/wms/commands/shared.js +9 -1
- package/dist/modules/wms/commands/shared.js.map +2 -2
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js +158 -0
- package/dist/modules/wms/components/backend/WarehouseEditDialog.js.map +7 -0
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js +76 -111
- package/dist/modules/wms/components/backend/WmsConfigurationPage.js.map +3 -3
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js +1 -0
- package/dist/modules/wms/components/backend/WmsInventoryConsolePage.js.map +2 -2
- package/dist/modules/wms/components/backend/WmsLotsListPage.js +1 -0
- package/dist/modules/wms/components/backend/WmsLotsListPage.js.map +2 -2
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js +27 -20
- package/dist/modules/wms/components/backend/inventoryMutationLoaders.js.map +2 -2
- package/dist/modules/wms/components/backend/warehouseFormOptions.js +66 -0
- package/dist/modules/wms/components/backend/warehouseFormOptions.js.map +7 -0
- package/dist/modules/workflows/backend/definitions/page.js +3 -1
- package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
- package/dist/modules/workflows/backend/events/page.js +3 -1
- package/dist/modules/workflows/backend/events/page.js.map +2 -2
- package/dist/modules/workflows/backend/instances/page.js +3 -1
- package/dist/modules/workflows/backend/instances/page.js.map +2 -2
- package/dist/modules/workflows/backend/tasks/page.js +3 -1
- package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
- package/dist/modules/workflows/lib/activity-executor.js +4 -0
- package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
- package/package.json +9 -10
- package/src/helpers/integration/api.ts +33 -1
- package/src/helpers/integration/communicationChannelsFixtures.ts +69 -1
- package/src/modules/api_keys/api/keys/route.ts +3 -1
- package/src/modules/api_keys/backend/api-keys/page.tsx +4 -1
- package/src/modules/api_keys/di.ts +7 -0
- package/src/modules/api_keys/services/principalService.ts +33 -0
- package/src/modules/attachments/AGENTS.md +15 -0
- package/src/modules/attachments/api/route.ts +2 -2
- package/src/modules/attachments/components/AttachmentLibrary.tsx +3 -0
- package/src/modules/attachments/di.ts +16 -0
- package/src/modules/attachments/i18n/de.json +5 -0
- package/src/modules/attachments/i18n/en.json +5 -0
- package/src/modules/attachments/i18n/es.json +5 -0
- package/src/modules/attachments/i18n/ko.json +5 -0
- package/src/modules/attachments/i18n/pl.json +5 -0
- package/src/modules/attachments/index.ts +10 -0
- package/src/modules/attachments/lib/attachment-service.ts +468 -0
- package/src/modules/attachments/lib/scoped-upload-service.ts +46 -0
- package/src/modules/attachments/lib/upload-limits.ts +6 -2
- package/src/modules/audit_logs/backend/audit-logs/page.tsx +8 -0
- package/src/modules/audit_logs/lib/display-helpers.tsx +42 -32
- package/src/modules/audit_logs/services/actionLogService.ts +74 -11
- package/src/modules/auth/acl.ts +30 -6
- package/src/modules/auth/api/feature-check.ts +10 -3
- package/src/modules/auth/api/login.ts +9 -1
- package/src/modules/auth/api/reset/validate.ts +57 -0
- package/src/modules/auth/api/roles/acl/route.ts +42 -39
- package/src/modules/auth/api/session/refresh.ts +32 -1
- package/src/modules/auth/api/users/acl/route.ts +177 -53
- package/src/modules/auth/api/users/route.ts +18 -5
- package/src/modules/auth/backend/roles/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/roles/page.tsx +4 -2
- package/src/modules/auth/backend/users/[id]/edit/page.meta.ts +5 -2
- package/src/modules/auth/backend/users/page.tsx +3 -2
- package/src/modules/auth/commands/acl.ts +495 -0
- package/src/modules/auth/components/AclEditor.tsx +63 -33
- package/src/modules/auth/data/entities.ts +4 -1
- package/src/modules/auth/data/validators.ts +5 -0
- package/src/modules/auth/di.ts +46 -16
- package/src/modules/auth/frontend/reset/[token]/page.tsx +74 -0
- package/src/modules/auth/i18n/de.json +389 -0
- package/src/modules/auth/i18n/en.json +389 -0
- package/src/modules/auth/i18n/es.json +389 -0
- package/src/modules/auth/i18n/ko.json +389 -0
- package/src/modules/auth/i18n/pl.json +391 -2
- package/src/modules/auth/lib/grantChecks.ts +6 -0
- package/src/modules/auth/lib/userIdFilter.ts +31 -0
- package/src/modules/auth/services/authService.ts +18 -2
- package/src/modules/auth/services/principalService.ts +266 -0
- package/src/modules/auth/services/rbacService.ts +110 -24
- package/src/modules/auth/services/roleOrganizationScope.ts +70 -0
- package/src/modules/business_rules/backend/logs/page.tsx +4 -1
- package/src/modules/business_rules/backend/rules/page.tsx +4 -1
- package/src/modules/business_rules/backend/sets/page.tsx +4 -1
- package/src/modules/business_rules/lib/expression-evaluator.ts +9 -9
- package/src/modules/business_rules/lib/rule-evaluator.ts +10 -9
- package/src/modules/catalog/ai-agents.ts +1 -1
- package/src/modules/catalog/ai-tools/merchandising-pack.ts +2 -2
- package/src/modules/catalog/backend/catalog/products/MerchandisingAssistantSheet.tsx +12 -5
- package/src/modules/catalog/components/categories/CategoriesDataTable.tsx +3 -0
- package/src/modules/catalog/components/products/ProductsDataTable.tsx +7 -0
- package/src/modules/catalog/i18n/de.json +1 -0
- package/src/modules/catalog/i18n/en.json +1 -0
- package/src/modules/catalog/i18n/es.json +1 -0
- package/src/modules/catalog/i18n/ko.json +1 -0
- package/src/modules/catalog/i18n/pl.json +1 -0
- package/src/modules/catalog/widgets/injection/merchandising-assistant-trigger/widget.client.tsx +4 -0
- package/src/modules/communication_channels/api/post/channels/[id]/test-send/route.ts +17 -1
- package/src/modules/communication_channels/api/post/test-seed/route.ts +155 -16
- package/src/modules/communication_channels/backend/communication_channels/channels/page.tsx +4 -0
- package/src/modules/communication_channels/commands/ingest-inbound-message.ts +38 -1
- package/src/modules/communication_channels/di.ts +7 -0
- package/src/modules/communication_channels/lib/adapter.ts +14 -0
- package/src/modules/communication_channels/lib/email-capabilities.ts +4 -0
- package/src/modules/communication_channels/lib/outbound-recipient.ts +71 -0
- package/src/modules/communication_channels/lib/resolve-channel-type.ts +99 -0
- package/src/modules/communication_channels/lib/test-seed.ts +64 -4
- package/src/modules/configs/i18n/de.json +2 -0
- package/src/modules/configs/i18n/en.json +2 -0
- package/src/modules/configs/i18n/es.json +2 -0
- package/src/modules/configs/i18n/ko.json +2 -0
- package/src/modules/configs/i18n/pl.json +2 -0
- package/src/modules/configs/lib/system-status.ts +9 -0
- package/src/modules/currencies/AGENTS.md +3 -0
- package/src/modules/currencies/backend/currencies/page.tsx +4 -1
- package/src/modules/currencies/backend/exchange-rates/page.tsx +4 -1
- package/src/modules/currencies/services/README.md +45 -0
- package/src/modules/currencies/services/rateFetchingService.ts +6 -1
- package/src/modules/customer_accounts/api/admin/domain-mappings.ts +7 -0
- package/src/modules/customer_accounts/backend/customer_accounts/roles/page.tsx +4 -1
- package/src/modules/customer_accounts/backend/customer_accounts/users/PortalUsersPageClient.tsx +4 -1
- package/src/modules/customer_accounts/services/domainMappingService.ts +10 -0
- package/src/modules/customers/ai-tools/companies-pack.ts +4 -1
- package/src/modules/customers/ai-tools/deal-analyzer-pack.ts +17 -2
- package/src/modules/customers/ai-tools/deals-pack.ts +66 -1
- package/src/modules/customers/ai-tools/people-pack.ts +4 -1
- package/src/modules/customers/api/activities/route.ts +45 -0
- package/src/modules/customers/api/companies/[id]/people/route.ts +24 -73
- package/src/modules/customers/api/companies/[id]/route.ts +24 -107
- package/src/modules/customers/api/dashboard/widgets/customer-todos/route.ts +16 -8
- package/src/modules/customers/api/deals/[id]/companies/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +4 -1
- package/src/modules/customers/api/deals/[id]/route.ts +17 -28
- package/src/modules/customers/api/deals/[id]/stats/route.ts +10 -25
- package/src/modules/customers/api/deals/aggregate/route.ts +14 -4
- package/src/modules/customers/api/deals/map/route.ts +1 -0
- package/src/modules/customers/api/deals/route.ts +50 -1
- package/src/modules/customers/api/entity-roles-factory.ts +8 -4
- package/src/modules/customers/api/interactions/route.ts +8 -2
- package/src/modules/customers/api/interactions/tasks/route.ts +24 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +12 -4
- package/src/modules/customers/api/people/[id]/companies/context.ts +4 -1
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +4 -1
- package/src/modules/customers/api/people/[id]/route.ts +16 -11
- package/src/modules/customers/api/people/check-phone/route.ts +75 -10
- package/src/modules/customers/api/todos/route.ts +27 -2
- package/src/modules/customers/backend/customers/companies/page.tsx +5 -2
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +7 -2
- package/src/modules/customers/backend/customers/deals/page.tsx +8 -2
- package/src/modules/customers/backend/customers/deals/pipeline/components/Lane.tsx +5 -14
- package/src/modules/customers/backend/customers/deals/pipeline/components/StatusFilterPopover.tsx +109 -27
- package/src/modules/customers/backend/customers/deals/pipeline/components/toneClasses.ts +21 -0
- package/src/modules/customers/backend/customers/people/page.tsx +5 -2
- package/src/modules/customers/backend/hooks/useEmailDuplicateCheck.ts +12 -4
- package/src/modules/customers/commands/deals.ts +34 -59
- package/src/modules/customers/commands/interactions.ts +1 -1
- package/src/modules/customers/commands/personCompanyLinks.ts +224 -8
- package/src/modules/customers/components/CustomerTodosTable.tsx +2 -0
- package/src/modules/customers/components/DealsKpiStrip.tsx +7 -7
- package/src/modules/customers/components/calendar/AgendaList.tsx +3 -3
- package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarScreen.tsx +1 -1
- package/src/modules/customers/components/calendar/CalendarSettingsModal.tsx +1 -1
- package/src/modules/customers/components/calendar/EventBlock.tsx +2 -2
- package/src/modules/customers/components/calendar/EventPeekPopover.tsx +4 -2
- package/src/modules/customers/components/calendar/editor/PeopleField.tsx +61 -5
- package/src/modules/customers/components/calendar/editor/hooks.ts +7 -1
- package/src/modules/customers/components/calendar/types.ts +2 -2
- package/src/modules/customers/components/detail/CompanyKpiBar.tsx +5 -4
- package/src/modules/customers/components/detail/CompanyPeopleSection.tsx +8 -1
- package/src/modules/customers/components/detail/DealForm.tsx +22 -2
- package/src/modules/customers/components/detail/DealsSection.tsx +11 -5
- package/src/modules/customers/components/detail/EntityTagsDialog.tsx +58 -12
- package/src/modules/customers/components/detail/PersonCompaniesSection.tsx +8 -1
- package/src/modules/customers/components/detail/hooks/usePersonTasks.ts +23 -14
- package/src/modules/customers/components/detail/schedule/ParticipantsField.tsx +5 -5
- package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +5 -5
- package/src/modules/customers/components/detail/types.ts +1 -1
- package/src/modules/customers/components/detail/utils.ts +15 -5
- package/src/modules/customers/data/entities.ts +1 -1
- package/src/modules/customers/data/validators.ts +50 -9
- package/src/modules/customers/events.ts +5 -0
- package/src/modules/customers/i18n/de.json +9 -1
- package/src/modules/customers/i18n/en.json +9 -1
- package/src/modules/customers/i18n/es.json +9 -1
- package/src/modules/customers/i18n/ko.json +9 -1
- package/src/modules/customers/i18n/pl.json +9 -1
- package/src/modules/customers/lib/calendar/conflicts.ts +10 -2
- package/src/modules/customers/lib/calendar/editorPayload.ts +4 -3
- package/src/modules/customers/lib/calendar/mapItem.ts +8 -3
- package/src/modules/customers/lib/calendar/participantIdentity.ts +17 -0
- package/src/modules/customers/lib/closureStage.ts +76 -0
- package/src/modules/customers/lib/dealStatus.ts +42 -0
- package/src/modules/customers/lib/detailReadAccess.ts +35 -0
- package/src/modules/customers/lib/findPeopleByAddresses.ts +8 -6
- package/src/modules/customers/lib/personCompanies.ts +136 -1
- package/src/modules/customers/lib/todoCompatibility.ts +19 -1
- package/src/modules/dashboards/i18n/es.json +4 -4
- package/src/modules/dashboards/i18n/pl.json +7 -7
- package/src/modules/dashboards/lib/widgetScope.ts +6 -0
- package/src/modules/data_sync/AGENTS.md +1 -1
- package/src/modules/data_sync/backend/data-sync/page.tsx +4 -1
- package/src/modules/data_sync/lib/abandoned-run.ts +56 -0
- package/src/modules/data_sync/lib/adapter.ts +36 -0
- package/src/modules/data_sync/lib/sync-engine.ts +113 -5
- package/src/modules/data_sync/workers/sync-export.ts +4 -0
- package/src/modules/data_sync/workers/sync-import.ts +4 -0
- package/src/modules/devices/AGENTS.md +20 -1
- package/src/modules/devices/acl.ts +9 -1
- package/src/modules/devices/api/admin/devices/[id]/route.ts +5 -34
- package/src/modules/devices/api/admin/devices/route.ts +14 -1
- package/src/modules/devices/api/deviceList.ts +135 -11
- package/src/modules/devices/api/deviceSerialization.ts +50 -0
- package/src/modules/devices/api/openapi.ts +9 -1
- package/src/modules/devices/api/route.ts +9 -1
- package/src/modules/devices/backend/devices/[id]/page.tsx +18 -32
- package/src/modules/devices/backend/devices/create/page.tsx +17 -1
- package/src/modules/devices/backend/devices/page.tsx +44 -45
- package/src/modules/devices/backend/devices/useDeviceUserLabels.ts +45 -0
- package/src/modules/devices/backend/devices/userOptions.ts +99 -0
- package/src/modules/devices/i18n/de.json +3 -2
- package/src/modules/devices/i18n/en.json +3 -2
- package/src/modules/devices/i18n/es.json +3 -2
- package/src/modules/devices/i18n/ko.json +3 -2
- package/src/modules/devices/i18n/pl.json +3 -2
- package/src/modules/devices/setup.ts +6 -2
- package/src/modules/directory/backend/directory/organizations/page.tsx +3 -1
- package/src/modules/directory/backend/directory/tenants/page.tsx +3 -1
- package/src/modules/directory/di.ts +14 -2
- package/src/modules/directory/services/organizationHierarchyService.ts +34 -0
- package/src/modules/directory/services/organizationScopeService.ts +85 -0
- package/src/modules/directory/utils/organizationScope.ts +4 -15
- package/src/modules/entities/api/records.ts +2 -0
- package/src/modules/entities/backend/entities/user/[entityId]/records/page.tsx +4 -1
- package/src/modules/eudr/api/plots/route.ts +4 -0
- package/src/modules/eudr/backend/eudr/evidence-submissions/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/plots/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/product-mappings/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/risk-assessments/page.tsx +4 -0
- package/src/modules/eudr/backend/eudr/statements/page.tsx +4 -0
- package/src/modules/eudr/commands/statements.ts +0 -3
- package/src/modules/eudr/data/validators.ts +16 -1
- package/src/modules/feature_toggles/components/FeatureTogglesTable.tsx +2 -1
- package/src/modules/feature_toggles/components/OverridesTable.tsx +2 -1
- package/src/modules/feature_toggles/defaults.json +0 -8
- package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +4 -0
- package/src/modules/inbox_ops/backend/inbox-ops/page.tsx +4 -0
- package/src/modules/inbox_ops/lib/htmlToPlainText.ts +1 -17
- package/src/modules/integrations/api/[id]/credentials/route.ts +6 -4
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +61 -31
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +44 -9
- package/src/modules/integrations/backend/integrations/credential-secret-fields.ts +84 -0
- package/src/modules/integrations/data/validators.ts +12 -2
- package/src/modules/integrations/i18n/de.json +1 -0
- package/src/modules/integrations/i18n/en.json +1 -0
- package/src/modules/integrations/i18n/es.json +1 -0
- package/src/modules/integrations/i18n/ko.json +1 -0
- package/src/modules/integrations/i18n/pl.json +1 -0
- package/src/modules/integrations/lib/credentials-masking.ts +10 -6
- package/src/modules/messages/api/[id]/route.ts +55 -1
- package/src/modules/messages/api/openapi.ts +20 -0
- package/src/modules/messages/api/route.ts +31 -2
- package/src/modules/messages/components/MessagesInboxPageClient.tsx +9 -16
- package/src/modules/messages/components/inboxFilters.ts +36 -0
- package/src/modules/messages/components/message-detail/hooks/useMessageDetailsConversation.ts +14 -1
- package/src/modules/messages/components/message-detail/panels/MessageHeader.tsx +3 -1
- package/src/modules/messages/components/message-detail/panels/thread-panel.tsx +2 -1
- package/src/modules/messages/components/message-detail/types.ts +3 -0
- package/src/modules/messages/components/messageListLabels.ts +52 -3
- package/src/modules/messages/data/validators.ts +43 -4
- package/src/modules/messages/lib/channel-sender-identity.ts +55 -0
- package/src/modules/messages/lib/composeSourceChannelType.ts +95 -0
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +4 -6
- package/src/modules/payment_gateways/backend/payment-gateways/page.tsx +4 -1
- package/src/modules/payment_gateways/lib/webhook-processor.ts +11 -0
- package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -0
- package/src/modules/push_notifications/backend/push_notifications/page.tsx +4 -1
- package/src/modules/push_notifications/backend/push_notifications/send/page.tsx +4 -4
- package/src/modules/query_index/lib/engine.ts +249 -61
- package/src/modules/query_index/lib/search-entity-policy.ts +46 -0
- package/src/modules/query_index/lib/search-tokens.ts +135 -3
- package/src/modules/resources/backend/resources/resource-types/page.tsx +4 -1
- package/src/modules/resources/backend/resources/resources/page.tsx +4 -1
- package/src/modules/sales/backend/sales/channels/offers/page.tsx +4 -0
- package/src/modules/sales/backend/sales/channels/page.tsx +4 -0
- package/src/modules/sales/backend/sales/documents/[id]/page.tsx +14 -8
- package/src/modules/sales/commands/documents.ts +93 -0
- package/src/modules/sales/components/PriceWithCurrency.tsx +17 -5
- package/src/modules/sales/components/channels/SalesChannelOffersPanel.tsx +4 -0
- package/src/modules/sales/components/documents/AdjustmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/ItemsSection.tsx +56 -18
- package/src/modules/sales/components/documents/LineItemDialog.tsx +137 -20
- package/src/modules/sales/components/documents/PaymentsSection.tsx +20 -9
- package/src/modules/sales/components/documents/ReturnsSection.tsx +6 -5
- package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +106 -14
- package/src/modules/sales/components/documents/SalesOrderDraftLines.tsx +6 -5
- package/src/modules/sales/components/documents/ShipmentDialog.tsx +5 -4
- package/src/modules/sales/components/documents/ShipmentsSection.tsx +6 -5
- package/src/modules/sales/components/documents/lineItemShipmentLock.ts +74 -0
- package/src/modules/sales/components/documents/lineItemUtils.ts +7 -2
- package/src/modules/sales/data/entities.ts +6 -0
- package/src/modules/sales/extension-points.ts +1 -0
- package/src/modules/sales/i18n/de.json +8 -0
- package/src/modules/sales/i18n/en.json +8 -0
- package/src/modules/sales/i18n/es.json +8 -0
- package/src/modules/sales/i18n/ko.json +8 -0
- package/src/modules/sales/i18n/pl.json +8 -0
- package/src/modules/sales/lib/salesChannelsToggleSeed.ts +42 -0
- package/src/modules/sales/migrations/.snapshot-open-mercato.json +60 -0
- package/src/modules/sales/migrations/Migration20260821120000_sales_notes_addresses_context_idx.ts +87 -0
- package/src/modules/sales/setup.ts +2 -0
- package/src/modules/sales/widgets/injection/payment-gateway-status-column/widget.ts +9 -1
- package/src/modules/sales/widgets/injection-table.ts +4 -7
- package/src/modules/staff/backend/staff/leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +4 -0
- package/src/modules/staff/backend/staff/team-members/page.tsx +6 -0
- package/src/modules/staff/backend/staff/team-roles/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -0
- package/src/modules/staff/backend/staff/teams/page.tsx +4 -0
- package/src/modules/staff/backend/staff/timesheets/page.tsx +12 -1
- package/src/modules/staff/backend/staff/timesheets/projects/page.tsx +4 -0
- package/src/modules/sync_excel/lib/adapters/customers.ts +5 -0
- package/src/modules/warranty_claims/api/assignees/route.ts +3 -3
- package/src/modules/warranty_claims/api/portal/attachments/route.ts +2 -2
- package/src/modules/warranty_claims/api/portal/claims/route.ts +12 -9
- package/src/modules/warranty_claims/backend/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/registrations/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/troubleshooting-guides/page.tsx +4 -0
- package/src/modules/warranty_claims/backend/warranty_claims/vendor-policies/page.tsx +4 -0
- package/src/modules/warranty_claims/frontend/[orgSlug]/portal/claims/page.tsx +4 -0
- package/src/modules/wms/api/warehouseSearch.ts +23 -0
- package/src/modules/wms/api/warehouses/route.ts +13 -9
- package/src/modules/wms/api/zones/route.ts +16 -0
- package/src/modules/wms/commands/configuration.ts +159 -10
- package/src/modules/wms/commands/inventory-actions.ts +3 -0
- package/src/modules/wms/commands/shared.ts +17 -0
- package/src/modules/wms/components/backend/WarehouseEditDialog.tsx +216 -0
- package/src/modules/wms/components/backend/WmsConfigurationPage.tsx +95 -141
- package/src/modules/wms/components/backend/WmsInventoryConsolePage.tsx +2 -0
- package/src/modules/wms/components/backend/WmsLotsListPage.tsx +2 -0
- package/src/modules/wms/components/backend/inventoryMutationLoaders.ts +36 -20
- package/src/modules/wms/components/backend/warehouseFormOptions.ts +72 -0
- package/src/modules/wms/i18n/de.json +2 -0
- package/src/modules/wms/i18n/en.json +2 -0
- package/src/modules/wms/i18n/es.json +2 -0
- package/src/modules/wms/i18n/ko.json +2 -0
- package/src/modules/wms/i18n/pl.json +2 -0
- package/src/modules/workflows/backend/definitions/page.tsx +4 -1
- package/src/modules/workflows/backend/events/page.tsx +4 -1
- package/src/modules/workflows/backend/instances/page.tsx +4 -1
- package/src/modules/workflows/backend/tasks/page.tsx +4 -1
- package/src/modules/workflows/lib/activity-executor.ts +9 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Auth ACL Commands — Undo Policy
|
|
3
|
+
// =============================================================================
|
|
4
|
+
//
|
|
5
|
+
// Neither command in this file defines `undo` or `redo`, so the command bus
|
|
6
|
+
// never mints an undo token for them: `CommandBus.isUndoable()` requires a
|
|
7
|
+
// handler-provided `undo`. The explicit `isUndoable: false` below is executable
|
|
8
|
+
// documentation of that intent, not the mechanism — the guarantee comes from
|
|
9
|
+
// the absence of the handlers, and the unit tests pin both.
|
|
10
|
+
//
|
|
11
|
+
// The policy is deliberate even though an ACL grant is trivially reversible.
|
|
12
|
+
// The undo and redo endpoints are gated on `audit_logs.undo_self` /
|
|
13
|
+
// `audit_logs.undo_tenant` (and their redo counterparts), not on
|
|
14
|
+
// `auth.acl.manage`. `audit_logs.undo_self` is a default `employee` grant and
|
|
15
|
+
// `audit_logs.undo_tenant` reaches every `admin` through `audit_logs.*`, so an
|
|
16
|
+
// undoable ACL command would let a caller revert or replay someone else's
|
|
17
|
+
// permission change without ever holding the feature that authorizes editing
|
|
18
|
+
// permissions.
|
|
19
|
+
//
|
|
20
|
+
// Reversal stays available to the callers who are actually authorized for it:
|
|
21
|
+
// re-submitting the ACL form, gated on `auth.acl.manage` and guarded by
|
|
22
|
+
// `assertActorCanGrantAcl`. The audit log still captures the full before/after
|
|
23
|
+
// via `buildLog`, so any such correction is itself fully traceable.
|
|
24
|
+
// =============================================================================
|
|
25
|
+
import type { CommandHandler, CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
26
|
+
import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
27
|
+
import { snapshotsEqual } from '@open-mercato/shared/lib/commands/helpers'
|
|
28
|
+
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
29
|
+
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
30
|
+
import { createLogger } from '@open-mercato/shared/lib/logger'
|
|
31
|
+
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
32
|
+
import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'
|
|
33
|
+
import { Role, RoleAcl, User, UserAcl } from '@open-mercato/core/modules/auth/data/entities'
|
|
34
|
+
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
35
|
+
|
|
36
|
+
const logger = createLogger('auth').child({ component: 'acl-commands' })
|
|
37
|
+
|
|
38
|
+
type TaggableCache = { deleteByTags?: (tags: string[]) => Promise<void> | void }
|
|
39
|
+
|
|
40
|
+
/** Structural view of the fields both `RoleAcl` and `UserAcl` expose. */
|
|
41
|
+
type AclRecord = {
|
|
42
|
+
isSuperAdmin: boolean
|
|
43
|
+
featuresJson?: string[] | null
|
|
44
|
+
organizationsJson?: string[] | null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Audit snapshot of a single ACL row.
|
|
49
|
+
*
|
|
50
|
+
* `features` and `organizations` are grant *sets*, but `features_json` /
|
|
51
|
+
* `organizations_json` preserve the client's insertion order. The command bus
|
|
52
|
+
* derives `changes` from these snapshots with a deep equality check that is
|
|
53
|
+
* order-sensitive for arrays, so an unsorted snapshot would report a spurious
|
|
54
|
+
* `features` change every time an admin re-saves an unmodified form. Sorting
|
|
55
|
+
* here makes the derived diff reflect real grant changes only.
|
|
56
|
+
*
|
|
57
|
+
* `organizations: null` (visible in every organization) is deliberately
|
|
58
|
+
* distinct from `[]` (visible in none).
|
|
59
|
+
*/
|
|
60
|
+
type AclSnapshot = {
|
|
61
|
+
isSuperAdmin: boolean
|
|
62
|
+
features: string[]
|
|
63
|
+
organizations: string[] | null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const EMPTY_ACL_SNAPSHOT: AclSnapshot = {
|
|
67
|
+
isSuperAdmin: false,
|
|
68
|
+
features: [],
|
|
69
|
+
organizations: null,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Identity of the role or user an entry is about.
|
|
74
|
+
*
|
|
75
|
+
* `action_logs` keeps only `resource_id`, so an entry degrades to a bare UUID
|
|
76
|
+
* the moment the role or account is deleted — exactly when the trail matters
|
|
77
|
+
* most. This rides in `context` rather than in the snapshots because the
|
|
78
|
+
* command bus derives `changes` from the two snapshots with a deep comparison:
|
|
79
|
+
* a target renamed between two ACL edits would otherwise be reported as a
|
|
80
|
+
* permission change, and the no-op guard below would stop recognising an
|
|
81
|
+
* unchanged ACL.
|
|
82
|
+
*/
|
|
83
|
+
type AclTarget =
|
|
84
|
+
| { kind: 'user'; id: string; email: string | null; name: string | null }
|
|
85
|
+
| { kind: 'role'; id: string; name: string | null }
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* What the caller asked for when the route trimmed the request instead of
|
|
89
|
+
* refusing it.
|
|
90
|
+
*
|
|
91
|
+
* `sanitizeTenantFeatures` drops restricted grants silently, so such a request
|
|
92
|
+
* leaves `before` and `after` identical and is indistinguishable from a no-op —
|
|
93
|
+
* which `buildLog` skips. Recording the original request both keeps the attempt
|
|
94
|
+
* visible and exempts the entry from that guard.
|
|
95
|
+
*
|
|
96
|
+
* Features are the only axis carried, because they are the only one the route
|
|
97
|
+
* can trim: a super-admin request is honoured or refused outright, and
|
|
98
|
+
* organizations are never sanitized. Recording either would put a value next to
|
|
99
|
+
* the snapshots that always matches them, inviting a reader to diff the two and
|
|
100
|
+
* conclude a grant was refused.
|
|
101
|
+
*/
|
|
102
|
+
type SanitizedAclRequest = {
|
|
103
|
+
features: string[]
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** How the change reads at a glance, without diffing two grant lists. */
|
|
107
|
+
type AclChangeEffect = 'granted' | 'changed' | 'revoked'
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Codepoint ordering rather than `localeCompare`: these snapshots are persisted
|
|
111
|
+
* audit records, so the ordering must not shift with the runtime's default
|
|
112
|
+
* locale. Feature and organization ids are opaque ASCII identifiers that are
|
|
113
|
+
* never shown in this order to a user.
|
|
114
|
+
*
|
|
115
|
+
* The default comparator would coerce and compare the same way today, but
|
|
116
|
+
* omitting one is banned repo-wide (`explicit-sort-comparators.test.ts`,
|
|
117
|
+
* #3620): the ordering must be stated rather than inherited, so it cannot
|
|
118
|
+
* silently change meaning if a call site ever drifts to non-strings. This is
|
|
119
|
+
* the canonical-key form that audit prescribes.
|
|
120
|
+
*/
|
|
121
|
+
function compareIdentifiers(left: string, right: string): number {
|
|
122
|
+
if (left === right) return 0
|
|
123
|
+
return left < right ? -1 : 1
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function toSortedList(values: unknown): string[] {
|
|
127
|
+
if (!Array.isArray(values)) return []
|
|
128
|
+
return [...values].filter((value): value is string => typeof value === 'string').sort(compareIdentifiers)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function captureAclSnapshot(acl: AclRecord | null | undefined): AclSnapshot {
|
|
132
|
+
if (!acl) return { ...EMPTY_ACL_SNAPSHOT }
|
|
133
|
+
return {
|
|
134
|
+
isSuperAdmin: Boolean(acl.isSuperAdmin),
|
|
135
|
+
features: toSortedList(acl.featuresJson),
|
|
136
|
+
organizations: Array.isArray(acl.organizationsJson) ? toSortedList(acl.organizationsJson) : null,
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function holdsGrants(snapshot: AclSnapshot): boolean {
|
|
141
|
+
return snapshot.isSuperAdmin || snapshot.features.length > 0
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function resolveEffect(before: AclSnapshot, after: AclSnapshot): AclChangeEffect {
|
|
145
|
+
if (!holdsGrants(before) && holdsGrants(after)) return 'granted'
|
|
146
|
+
if (holdsGrants(before) && !holdsGrants(after)) return 'revoked'
|
|
147
|
+
return 'changed'
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function resolveEm(ctx: CommandRuntimeContext): EntityManager {
|
|
151
|
+
return ctx.container.resolve('em') as EntityManager
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* The log row's organization must belong to the same tenant as the row itself.
|
|
156
|
+
*
|
|
157
|
+
* A super admin may edit a role in a tenant other than their own, and
|
|
158
|
+
* `ActionLogService.buildListQuery` filters with strict equality
|
|
159
|
+
* (`organization_id = ?`, applied only when the reader supplies one). Stamping
|
|
160
|
+
* the actor's organization onto a row scoped to a different tenant produces a
|
|
161
|
+
* (tenant B, organization from tenant A) pair that no reader can ever match, so
|
|
162
|
+
* the cross-tenant permission change — exactly the record worth keeping —
|
|
163
|
+
* becomes invisible. `null` is the honest value there: it still reaches
|
|
164
|
+
* tenant-scoped readers whose organization filter is unset.
|
|
165
|
+
*/
|
|
166
|
+
function resolveOrganizationId(ctx: CommandRuntimeContext, tenantId: string): string | null {
|
|
167
|
+
if ((ctx.auth?.tenantId ?? null) !== tenantId) return null
|
|
168
|
+
return ctx.selectedOrganizationId ?? ctx.auth?.orgId ?? null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* A runtime with no cache registered (CLI, workers, tests) is a configuration,
|
|
173
|
+
* not a failure, so resolution is guarded here. An adapter that *is* wired and
|
|
174
|
+
* then throws is a failure, and it propagates to the single error-level guard
|
|
175
|
+
* in `execute` — the same one that covers the `rbacService` half of this
|
|
176
|
+
* invalidation. Reporting one half at `debug` and the other at `error` would
|
|
177
|
+
* hide a nav cache still serving revoked grants.
|
|
178
|
+
*/
|
|
179
|
+
async function deleteCacheTags(ctx: CommandRuntimeContext, tags: string[]): Promise<void> {
|
|
180
|
+
let cache: TaggableCache | undefined
|
|
181
|
+
try {
|
|
182
|
+
cache = ctx.container.resolve('cache') as TaggableCache | undefined
|
|
183
|
+
} catch (err) {
|
|
184
|
+
logger.debug('No cache registered for ACL tag invalidation', { err, tags })
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
if (!cache?.deleteByTags) return
|
|
188
|
+
await cache.deleteByTags(tags)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
type AclCommandValues = {
|
|
192
|
+
isSuperAdmin: boolean
|
|
193
|
+
features: string[]
|
|
194
|
+
organizations: string[] | null
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
type AclCommandInput = AclCommandValues & { tenantId: string }
|
|
198
|
+
|
|
199
|
+
export type RoleAclUpdateInput = AclCommandInput & {
|
|
200
|
+
roleId: string
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export type UserAclUpdateInput = AclCommandInput & {
|
|
204
|
+
userId: string
|
|
205
|
+
/** Mirrors the route's `!hasCustomAcl`: drop the override row instead of upserting it. */
|
|
206
|
+
clear: boolean
|
|
207
|
+
/** Set by the route only when it wrote less than the caller asked for. */
|
|
208
|
+
requested?: SanitizedAclRequest | null
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export type AclUpdateResult = {
|
|
212
|
+
resourceId: string
|
|
213
|
+
tenantId: string
|
|
214
|
+
organizationId: string | null
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const AUTH_ROLE_ACL_UPDATE_COMMAND_ID = 'auth.role-acl.update'
|
|
218
|
+
export const AUTH_USER_ACL_UPDATE_COMMAND_ID = 'auth.user-acl.update'
|
|
219
|
+
|
|
220
|
+
type AclCommandConfig<TInput extends AclCommandInput> = {
|
|
221
|
+
id: string
|
|
222
|
+
resourceKind: string
|
|
223
|
+
labelKey: string
|
|
224
|
+
labelFallback: string
|
|
225
|
+
resourceId: (input: TInput) => string
|
|
226
|
+
loadAcl: (em: EntityManager, input: TInput) => Promise<AclRecord | null>
|
|
227
|
+
persist: (params: { em: EntityManager; input: TInput; existing: AclRecord | null }) => Promise<void>
|
|
228
|
+
invalidate: (params: { ctx: CommandRuntimeContext; input: TInput }) => Promise<void>
|
|
229
|
+
/**
|
|
230
|
+
* Post-state when the row is absent after the write. Only the user command's
|
|
231
|
+
* clear path legitimately removes the row; anywhere else a missing row means
|
|
232
|
+
* the re-read failed, which must be logged as "unknown" rather than guessed.
|
|
233
|
+
*/
|
|
234
|
+
snapshotWhenAbsent: (input: TInput) => AclSnapshot | null
|
|
235
|
+
/** Human-readable identity of the target; `null` when it cannot be resolved. */
|
|
236
|
+
loadTarget: (em: EntityManager, input: TInput, ctx: CommandRuntimeContext) => Promise<AclTarget | null>
|
|
237
|
+
/** Only the user route sanitizes, so only it can report a trimmed request. */
|
|
238
|
+
sanitizedRequest?: (input: TInput) => SanitizedAclRequest | null
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Enrichment must never cost the entry.
|
|
243
|
+
*
|
|
244
|
+
* The bus persists the log after `execute` has already committed the permission
|
|
245
|
+
* change, so a throw from the target lookup would leave the write recorded
|
|
246
|
+
* nowhere — the same "committed but unaudited" hole the cache-invalidation
|
|
247
|
+
* guard in `execute` closes. A missing label is a far smaller loss.
|
|
248
|
+
*/
|
|
249
|
+
async function loadTargetSafely<TInput extends AclCommandInput>(
|
|
250
|
+
config: AclCommandConfig<TInput>,
|
|
251
|
+
input: TInput,
|
|
252
|
+
ctx: CommandRuntimeContext,
|
|
253
|
+
): Promise<AclTarget | null> {
|
|
254
|
+
try {
|
|
255
|
+
return await config.loadTarget(resolveEm(ctx).fork(), input, ctx)
|
|
256
|
+
} catch (err) {
|
|
257
|
+
logger.warn('Could not resolve the ACL target for the audit entry', {
|
|
258
|
+
err,
|
|
259
|
+
commandId: config.id,
|
|
260
|
+
resourceId: config.resourceId(input),
|
|
261
|
+
tenantId: input.tenantId,
|
|
262
|
+
})
|
|
263
|
+
return null
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function buildAuditContext(params: {
|
|
268
|
+
target: AclTarget | null
|
|
269
|
+
effect: AclChangeEffect | null
|
|
270
|
+
sanitizedRequest: SanitizedAclRequest | null
|
|
271
|
+
}): Record<string, unknown> | null {
|
|
272
|
+
const context: Record<string, unknown> = {}
|
|
273
|
+
if (params.target) context.target = params.target
|
|
274
|
+
if (params.effect) context.effect = params.effect
|
|
275
|
+
if (params.sanitizedRequest) context.sanitizedRequest = params.sanitizedRequest
|
|
276
|
+
return Object.keys(context).length ? context : null
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Both ACL commands differ only in entity, lookup key, cache invalidation and
|
|
281
|
+
* labels — `prepare`, `captureAfter` and `buildLog` are otherwise identical.
|
|
282
|
+
* Sharing them here keeps the two audit-entry shapes from drifting apart.
|
|
283
|
+
*/
|
|
284
|
+
function createAclUpdateCommand<TInput extends AclCommandInput>(
|
|
285
|
+
config: AclCommandConfig<TInput>,
|
|
286
|
+
): CommandHandler<TInput, AclUpdateResult> {
|
|
287
|
+
return {
|
|
288
|
+
id: config.id,
|
|
289
|
+
// See "Auth ACL Commands — Undo Policy" at top of file.
|
|
290
|
+
isUndoable: false,
|
|
291
|
+
async prepare(input, ctx) {
|
|
292
|
+
const existing = await config.loadAcl(resolveEm(ctx).fork(), input)
|
|
293
|
+
return { before: captureAclSnapshot(existing) }
|
|
294
|
+
},
|
|
295
|
+
async execute(input, ctx) {
|
|
296
|
+
const em = resolveEm(ctx)
|
|
297
|
+
const existing = await config.loadAcl(em, input)
|
|
298
|
+
await config.persist({ em, input, existing })
|
|
299
|
+
// Cache invalidation runs only after the write commits, never inside the
|
|
300
|
+
// atomic flush — and must never propagate. The command bus persists the
|
|
301
|
+
// action log *after* `execute` returns, so a throw here would commit the
|
|
302
|
+
// permission change and then suppress its audit entry: precisely the
|
|
303
|
+
// "committed but unaudited" hole these commands exist to close, and it
|
|
304
|
+
// would open exactly when infrastructure is already degraded.
|
|
305
|
+
// `RbacService.deleteCacheByTags` awaits the cache adapter without a
|
|
306
|
+
// guard of its own, so an outage does reach us here.
|
|
307
|
+
//
|
|
308
|
+
// The resulting staleness (a revoked grant served from cache until its
|
|
309
|
+
// TTL) is not introduced by swallowing — it happens either way once the
|
|
310
|
+
// adapter is down. Logging at error level keeps it alarmable instead of
|
|
311
|
+
// trading a recorded change for an HTTP 500 that misreports a write which
|
|
312
|
+
// did commit.
|
|
313
|
+
try {
|
|
314
|
+
await config.invalidate({ ctx, input })
|
|
315
|
+
} catch (err) {
|
|
316
|
+
logger.error('ACL cache invalidation failed after a committed permission change', {
|
|
317
|
+
err,
|
|
318
|
+
commandId: config.id,
|
|
319
|
+
resourceId: config.resourceId(input),
|
|
320
|
+
tenantId: input.tenantId,
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
resourceId: config.resourceId(input),
|
|
325
|
+
tenantId: input.tenantId,
|
|
326
|
+
organizationId: resolveOrganizationId(ctx, input.tenantId),
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
captureAfter: async (input, _result, ctx) => {
|
|
330
|
+
// Read the committed row back rather than echoing the request, so a grant
|
|
331
|
+
// the route sanitized away can never be logged as if it had been applied.
|
|
332
|
+
const persisted = await config.loadAcl(resolveEm(ctx).fork(), input)
|
|
333
|
+
if (persisted) return captureAclSnapshot(persisted)
|
|
334
|
+
return config.snapshotWhenAbsent(input)
|
|
335
|
+
},
|
|
336
|
+
buildLog: async ({ input, result, ctx, snapshots }) => {
|
|
337
|
+
const before = (snapshots.before as AclSnapshot | undefined) ?? null
|
|
338
|
+
const after = (snapshots.after as AclSnapshot | undefined) ?? null
|
|
339
|
+
// An unknown post-state (`after: null`, the failed re-read) counts as a
|
|
340
|
+
// change: it is the one case where the entry is the only evidence left.
|
|
341
|
+
// Both snapshots leave `captureAclSnapshot` with their grant lists sorted,
|
|
342
|
+
// so the shared order-sensitive comparison is a set comparison here.
|
|
343
|
+
const changed = !before || !after || !snapshotsEqual(before, after)
|
|
344
|
+
const sanitizedRequest = config.sanitizedRequest?.(input) ?? null
|
|
345
|
+
// The admin user-edit page PUTs the ACL on every save, even when only the
|
|
346
|
+
// name or the roles changed, and most accounts carry no per-user override
|
|
347
|
+
// at all — so recording an unchanged ACL faithfully buries the real
|
|
348
|
+
// permission changes under identical empty entries. A request the route
|
|
349
|
+
// trimmed rather than refused also arrives with `before == after`; that
|
|
350
|
+
// one is an escalation attempt and must survive this guard.
|
|
351
|
+
if (!changed && !sanitizedRequest) return { skipLog: true }
|
|
352
|
+
const { translate } = await resolveTranslations()
|
|
353
|
+
const target = await loadTargetSafely(config, input, ctx)
|
|
354
|
+
return {
|
|
355
|
+
actionLabel: translate(config.labelKey, config.labelFallback),
|
|
356
|
+
resourceKind: config.resourceKind,
|
|
357
|
+
resourceId: result.resourceId,
|
|
358
|
+
tenantId: result.tenantId,
|
|
359
|
+
organizationId: result.organizationId,
|
|
360
|
+
snapshotBefore: before,
|
|
361
|
+
snapshotAfter: after,
|
|
362
|
+
context: buildAuditContext({
|
|
363
|
+
target,
|
|
364
|
+
// A sanitized-only entry is written *because* nothing changed, so
|
|
365
|
+
// labelling it would have the trail assert a permission change that
|
|
366
|
+
// never happened.
|
|
367
|
+
effect: changed && before && after ? resolveEffect(before, after) : null,
|
|
368
|
+
sanitizedRequest,
|
|
369
|
+
}),
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const updateRoleAclCommand = createAclUpdateCommand<RoleAclUpdateInput>({
|
|
376
|
+
id: AUTH_ROLE_ACL_UPDATE_COMMAND_ID,
|
|
377
|
+
resourceKind: 'auth.role_acl',
|
|
378
|
+
labelKey: 'auth.audit.roleAcl.update',
|
|
379
|
+
labelFallback: 'Change role permissions',
|
|
380
|
+
resourceId: (input) => input.roleId,
|
|
381
|
+
loadAcl: (em, input) =>
|
|
382
|
+
em.findOne(RoleAcl, { role: input.roleId as unknown as Role, tenantId: input.tenantId }),
|
|
383
|
+
persist: async ({ em, input, existing }) => {
|
|
384
|
+
const acl =
|
|
385
|
+
(existing as RoleAcl | null) ??
|
|
386
|
+
em.create(RoleAcl, {
|
|
387
|
+
role: em.getReference(Role, input.roleId),
|
|
388
|
+
tenantId: input.tenantId,
|
|
389
|
+
createdAt: new Date(),
|
|
390
|
+
isSuperAdmin: false,
|
|
391
|
+
})
|
|
392
|
+
await withAtomicFlush(
|
|
393
|
+
em,
|
|
394
|
+
[
|
|
395
|
+
() => {
|
|
396
|
+
acl.organizationsJson = input.organizations
|
|
397
|
+
acl.isSuperAdmin = input.isSuperAdmin
|
|
398
|
+
acl.featuresJson = input.features
|
|
399
|
+
em.persist(acl)
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
{ transaction: true, label: AUTH_ROLE_ACL_UPDATE_COMMAND_ID },
|
|
403
|
+
)
|
|
404
|
+
},
|
|
405
|
+
invalidate: async ({ ctx, input }) => {
|
|
406
|
+
// Every user in the tenant inherits this role's grants, so the whole tenant
|
|
407
|
+
// scope is invalidated.
|
|
408
|
+
const rbacService = ctx.container.resolve('rbacService') as RbacService
|
|
409
|
+
await rbacService.invalidateTenantCache(input.tenantId)
|
|
410
|
+
// Sidebar nav caches depend on RBAC; invalidate tenant scope nav caches
|
|
411
|
+
await deleteCacheTags(ctx, [`rbac:tenant:${input.tenantId}`])
|
|
412
|
+
},
|
|
413
|
+
snapshotWhenAbsent: () => null,
|
|
414
|
+
// Looked up by id alone: the entry already names this role through
|
|
415
|
+
// `resource_id`, and a tenant predicate would only blank the label when a
|
|
416
|
+
// super admin edits a role from outside the tenant scope they are writing in.
|
|
417
|
+
loadTarget: async (em, input) => {
|
|
418
|
+
const role = await em.findOne(Role, { id: input.roleId } as FilterQuery<Role>)
|
|
419
|
+
if (!role) return null
|
|
420
|
+
return { kind: 'role', id: input.roleId, name: role.name ?? null }
|
|
421
|
+
},
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
const updateUserAclCommand = createAclUpdateCommand<UserAclUpdateInput>({
|
|
425
|
+
id: AUTH_USER_ACL_UPDATE_COMMAND_ID,
|
|
426
|
+
resourceKind: 'auth.user_acl',
|
|
427
|
+
labelKey: 'auth.audit.userAcl.update',
|
|
428
|
+
labelFallback: 'Change user permissions',
|
|
429
|
+
resourceId: (input) => input.userId,
|
|
430
|
+
loadAcl: (em, input) =>
|
|
431
|
+
em.findOne(UserAcl, { user: input.userId as unknown as User, tenantId: input.tenantId }),
|
|
432
|
+
persist: async ({ em, input, existing }) => {
|
|
433
|
+
if (input.clear) {
|
|
434
|
+
if (!existing) return
|
|
435
|
+
const aclToRemove = existing as UserAcl
|
|
436
|
+
await withAtomicFlush(
|
|
437
|
+
em,
|
|
438
|
+
[
|
|
439
|
+
() => {
|
|
440
|
+
em.remove(aclToRemove)
|
|
441
|
+
},
|
|
442
|
+
],
|
|
443
|
+
{ transaction: true, label: AUTH_USER_ACL_UPDATE_COMMAND_ID },
|
|
444
|
+
)
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
const acl =
|
|
448
|
+
(existing as UserAcl | null) ??
|
|
449
|
+
em.create(UserAcl, {
|
|
450
|
+
user: em.getReference(User, input.userId),
|
|
451
|
+
tenantId: input.tenantId,
|
|
452
|
+
createdAt: new Date(),
|
|
453
|
+
isSuperAdmin: false,
|
|
454
|
+
})
|
|
455
|
+
await withAtomicFlush(
|
|
456
|
+
em,
|
|
457
|
+
[
|
|
458
|
+
() => {
|
|
459
|
+
acl.isSuperAdmin = input.isSuperAdmin
|
|
460
|
+
acl.featuresJson = input.features
|
|
461
|
+
acl.organizationsJson = input.organizations
|
|
462
|
+
em.persist(acl)
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
{ transaction: true, label: AUTH_USER_ACL_UPDATE_COMMAND_ID },
|
|
466
|
+
)
|
|
467
|
+
},
|
|
468
|
+
invalidate: async ({ ctx, input }) => {
|
|
469
|
+
const rbacService = ctx.container.resolve('rbacService') as RbacService
|
|
470
|
+
await rbacService.invalidateUserCache(input.userId)
|
|
471
|
+
await deleteCacheTags(ctx, [`rbac:user:${input.userId}`])
|
|
472
|
+
},
|
|
473
|
+
// Clearing removes the row, so an absent row is the real post-state here.
|
|
474
|
+
snapshotWhenAbsent: (input) => (input.clear ? { ...EMPTY_ACL_SNAPSHOT } : null),
|
|
475
|
+
// `userId` arrives in the request body and `auth:user` carries encrypted
|
|
476
|
+
// personal data, so the lookup is tenant-scoped: an id belonging to another
|
|
477
|
+
// tenant must not be decrypted under this scope and stamped into this
|
|
478
|
+
// tenant's trail. A global account (`users.tenant_id` is nullable) still
|
|
479
|
+
// resolves, mirroring how the role route widens its own lookup.
|
|
480
|
+
loadTarget: async (em, input, ctx) => {
|
|
481
|
+
const user = await findOneWithDecryption(
|
|
482
|
+
em,
|
|
483
|
+
User,
|
|
484
|
+
{ id: input.userId, $or: [{ tenantId: input.tenantId }, { tenantId: null }] } as FilterQuery<User>,
|
|
485
|
+
{},
|
|
486
|
+
{ tenantId: input.tenantId, organizationId: ctx.auth?.orgId ?? null },
|
|
487
|
+
)
|
|
488
|
+
if (!user) return null
|
|
489
|
+
return { kind: 'user', id: input.userId, email: user.email ?? null, name: user.name ?? null }
|
|
490
|
+
},
|
|
491
|
+
sanitizedRequest: (input) => input.requested ?? null,
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
registerCommand(updateRoleAclCommand)
|
|
495
|
+
registerCommand(updateUserAclCommand)
|