grm-shared-library 1.1.201 → 1.1.203
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/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/kafka/topics.js +26 -0
- package/dist/cjs/kafka/topics.js.map +1 -1
- package/dist/cjs/modules/common/constants/service.const.js +1 -0
- package/dist/cjs/modules/common/constants/service.const.js.map +1 -1
- package/dist/cjs/modules/permission/data/permissions.data.js +26 -0
- package/dist/cjs/modules/permission/data/permissions.data.js.map +1 -1
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js +40 -0
- package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/cjs/modules/permission/enums/permissions-module.enum.js +1 -0
- package/dist/cjs/modules/permission/enums/permissions-module.enum.js.map +1 -1
- package/dist/cjs/modules/role/data/roles.data.js +85 -0
- package/dist/cjs/modules/role/data/roles.data.js.map +1 -1
- package/dist/cjs/modules/socket/enums/redis-channel-name.enum.js +1 -0
- package/dist/cjs/modules/socket/enums/redis-channel-name.enum.js.map +1 -1
- package/dist/cjs/modules/socket/enums/room-type.enum.js +8 -0
- package/dist/cjs/modules/socket/enums/room-type.enum.js.map +1 -1
- package/dist/cjs/modules/socket/enums/socket-event-name.enum.js +5 -0
- package/dist/cjs/modules/socket/enums/socket-event-name.enum.js.map +1 -1
- package/dist/cjs/modules/support/constants/support-defaults.const.js +139 -0
- package/dist/cjs/modules/support/constants/support-defaults.const.js.map +1 -0
- package/dist/cjs/modules/support/constants/support-kafka.const.js +51 -0
- package/dist/cjs/modules/support/constants/support-kafka.const.js.map +1 -0
- package/dist/cjs/modules/support/dtos/create-support-ticket-message.dto.js +82 -0
- package/dist/cjs/modules/support/dtos/create-support-ticket-message.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/create-support-ticket.dto.js +169 -0
- package/dist/cjs/modules/support/dtos/create-support-ticket.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/customer-feedback.dto.js +401 -0
- package/dist/cjs/modules/support/dtos/customer-feedback.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-configuration.dto.js +732 -0
- package/dist/cjs/modules/support/dtos/support-configuration.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-related-entity.dto.js +38 -0
- package/dist/cjs/modules/support/dtos/support-related-entity.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-report-query.dto.js +127 -0
- package/dist/cjs/modules/support/dtos/support-report-query.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-sync.dto.js +175 -0
- package/dist/cjs/modules/support/dtos/support-sync.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-ticket-actions.dto.js +191 -0
- package/dist/cjs/modules/support/dtos/support-ticket-actions.dto.js.map +1 -0
- package/dist/cjs/modules/support/dtos/support-ticket-query.dto.js +225 -0
- package/dist/cjs/modules/support/dtos/support-ticket-query.dto.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-audit-action.enum.js +87 -0
- package/dist/cjs/modules/support/enums/support-audit-action.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-feedback.enum.js +110 -0
- package/dist/cjs/modules/support/enums/support-feedback.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-provider-code.enum.js +66 -0
- package/dist/cjs/modules/support/enums/support-provider-code.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-related-entity-type.enum.js +50 -0
- package/dist/cjs/modules/support/enums/support-related-entity-type.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-routing.enum.js +58 -0
- package/dist/cjs/modules/support/enums/support-routing.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-sla.enum.js +55 -0
- package/dist/cjs/modules/support/enums/support-sla.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-sync.enum.js +133 -0
- package/dist/cjs/modules/support/enums/support-sync.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-ticket-channel.enum.js +36 -0
- package/dist/cjs/modules/support/enums/support-ticket-channel.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-ticket-message.enum.js +54 -0
- package/dist/cjs/modules/support/enums/support-ticket-message.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-ticket-priority.enum.js +41 -0
- package/dist/cjs/modules/support/enums/support-ticket-priority.enum.js.map +1 -0
- package/dist/cjs/modules/support/enums/support-ticket-status.enum.js +138 -0
- package/dist/cjs/modules/support/enums/support-ticket-status.enum.js.map +1 -0
- package/dist/cjs/modules/support/index.js +60 -0
- package/dist/cjs/modules/support/index.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/customer-feedback.js +3 -0
- package/dist/cjs/modules/support/interfaces/customer-feedback.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-configuration.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-configuration.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-events.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-events.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-provider-descriptor.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-provider-descriptor.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-realtime.js +18 -0
- package/dist/cjs/modules/support/interfaces/support-realtime.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-reports.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-reports.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-sync.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-sync.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-ticket-message.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-ticket-message.js.map +1 -0
- package/dist/cjs/modules/support/interfaces/support-ticket.js +3 -0
- package/dist/cjs/modules/support/interfaces/support-ticket.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-feedback.util.js +66 -0
- package/dist/cjs/modules/support/utils/support-feedback.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-redaction.util.js +173 -0
- package/dist/cjs/modules/support/utils/support-redaction.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-routing.util.js +87 -0
- package/dist/cjs/modules/support/utils/support-routing.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-sla.util.js +239 -0
- package/dist/cjs/modules/support/utils/support-sla.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-status.util.js +93 -0
- package/dist/cjs/modules/support/utils/support-status.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-sync.util.js +151 -0
- package/dist/cjs/modules/support/utils/support-sync.util.js.map +1 -0
- package/dist/cjs/modules/support/utils/support-ticket-number.util.js +61 -0
- package/dist/cjs/modules/support/utils/support-ticket-number.util.js.map +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/kafka/topics.js +26 -0
- package/dist/esm/kafka/topics.js.map +1 -1
- package/dist/esm/modules/common/constants/service.const.js +1 -0
- package/dist/esm/modules/common/constants/service.const.js.map +1 -1
- package/dist/esm/modules/permission/data/permissions.data.js +26 -0
- package/dist/esm/modules/permission/data/permissions.data.js.map +1 -1
- package/dist/esm/modules/permission/enums/permission-actions.enum.js +40 -0
- package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
- package/dist/esm/modules/permission/enums/permissions-module.enum.js +1 -0
- package/dist/esm/modules/permission/enums/permissions-module.enum.js.map +1 -1
- package/dist/esm/modules/role/data/roles.data.js +85 -0
- package/dist/esm/modules/role/data/roles.data.js.map +1 -1
- package/dist/esm/modules/socket/enums/redis-channel-name.enum.js +1 -0
- package/dist/esm/modules/socket/enums/redis-channel-name.enum.js.map +1 -1
- package/dist/esm/modules/socket/enums/room-type.enum.js +8 -0
- package/dist/esm/modules/socket/enums/room-type.enum.js.map +1 -1
- package/dist/esm/modules/socket/enums/socket-event-name.enum.js +5 -0
- package/dist/esm/modules/socket/enums/socket-event-name.enum.js.map +1 -1
- package/dist/esm/modules/support/constants/support-defaults.const.js +136 -0
- package/dist/esm/modules/support/constants/support-defaults.const.js.map +1 -0
- package/dist/esm/modules/support/constants/support-kafka.const.js +48 -0
- package/dist/esm/modules/support/constants/support-kafka.const.js.map +1 -0
- package/dist/esm/modules/support/dtos/create-support-ticket-message.dto.js +77 -0
- package/dist/esm/modules/support/dtos/create-support-ticket-message.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/create-support-ticket.dto.js +165 -0
- package/dist/esm/modules/support/dtos/create-support-ticket.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/customer-feedback.dto.js +392 -0
- package/dist/esm/modules/support/dtos/customer-feedback.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-configuration.dto.js +716 -0
- package/dist/esm/modules/support/dtos/support-configuration.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-related-entity.dto.js +34 -0
- package/dist/esm/modules/support/dtos/support-related-entity.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-report-query.dto.js +123 -0
- package/dist/esm/modules/support/dtos/support-report-query.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-sync.dto.js +169 -0
- package/dist/esm/modules/support/dtos/support-sync.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-ticket-actions.dto.js +180 -0
- package/dist/esm/modules/support/dtos/support-ticket-actions.dto.js.map +1 -0
- package/dist/esm/modules/support/dtos/support-ticket-query.dto.js +221 -0
- package/dist/esm/modules/support/dtos/support-ticket-query.dto.js.map +1 -0
- package/dist/esm/modules/support/enums/support-audit-action.enum.js +84 -0
- package/dist/esm/modules/support/enums/support-audit-action.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-feedback.enum.js +107 -0
- package/dist/esm/modules/support/enums/support-feedback.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-provider-code.enum.js +63 -0
- package/dist/esm/modules/support/enums/support-provider-code.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-related-entity-type.enum.js +47 -0
- package/dist/esm/modules/support/enums/support-related-entity-type.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-routing.enum.js +55 -0
- package/dist/esm/modules/support/enums/support-routing.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-sla.enum.js +52 -0
- package/dist/esm/modules/support/enums/support-sla.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-sync.enum.js +130 -0
- package/dist/esm/modules/support/enums/support-sync.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-ticket-channel.enum.js +33 -0
- package/dist/esm/modules/support/enums/support-ticket-channel.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-ticket-message.enum.js +51 -0
- package/dist/esm/modules/support/enums/support-ticket-message.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-ticket-priority.enum.js +38 -0
- package/dist/esm/modules/support/enums/support-ticket-priority.enum.js.map +1 -0
- package/dist/esm/modules/support/enums/support-ticket-status.enum.js +135 -0
- package/dist/esm/modules/support/enums/support-ticket-status.enum.js.map +1 -0
- package/dist/esm/modules/support/index.js +44 -0
- package/dist/esm/modules/support/index.js.map +1 -0
- package/dist/esm/modules/support/interfaces/customer-feedback.js +2 -0
- package/dist/esm/modules/support/interfaces/customer-feedback.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-configuration.js +2 -0
- package/dist/esm/modules/support/interfaces/support-configuration.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-events.js +2 -0
- package/dist/esm/modules/support/interfaces/support-events.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-provider-descriptor.js +2 -0
- package/dist/esm/modules/support/interfaces/support-provider-descriptor.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-realtime.js +15 -0
- package/dist/esm/modules/support/interfaces/support-realtime.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-reports.js +2 -0
- package/dist/esm/modules/support/interfaces/support-reports.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-sync.js +2 -0
- package/dist/esm/modules/support/interfaces/support-sync.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-ticket-message.js +2 -0
- package/dist/esm/modules/support/interfaces/support-ticket-message.js.map +1 -0
- package/dist/esm/modules/support/interfaces/support-ticket.js +2 -0
- package/dist/esm/modules/support/interfaces/support-ticket.js.map +1 -0
- package/dist/esm/modules/support/utils/support-feedback.util.js +60 -0
- package/dist/esm/modules/support/utils/support-feedback.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-redaction.util.js +164 -0
- package/dist/esm/modules/support/utils/support-redaction.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-routing.util.js +82 -0
- package/dist/esm/modules/support/utils/support-routing.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-sla.util.js +229 -0
- package/dist/esm/modules/support/utils/support-sla.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-status.util.js +81 -0
- package/dist/esm/modules/support/utils/support-status.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-sync.util.js +142 -0
- package/dist/esm/modules/support/utils/support-sync.util.js.map +1 -0
- package/dist/esm/modules/support/utils/support-ticket-number.util.js +56 -0
- package/dist/esm/modules/support/utils/support-ticket-number.util.js.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/kafka/topics.d.ts +21 -0
- package/dist/types/modules/common/constants/service.const.d.ts +4 -0
- package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +21 -0
- package/dist/types/modules/permission/enums/permissions-module.enum.d.ts +2 -1
- package/dist/types/modules/socket/enums/redis-channel-name.enum.d.ts +2 -1
- package/dist/types/modules/socket/enums/room-type.enum.d.ts +8 -0
- package/dist/types/modules/socket/enums/socket-event-name.enum.d.ts +2 -1
- package/dist/types/modules/support/constants/support-defaults.const.d.ts +129 -0
- package/dist/types/modules/support/constants/support-kafka.const.d.ts +47 -0
- package/dist/types/modules/support/dtos/create-support-ticket-message.dto.d.ts +30 -0
- package/dist/types/modules/support/dtos/create-support-ticket.dto.d.ts +35 -0
- package/dist/types/modules/support/dtos/customer-feedback.dto.d.ts +83 -0
- package/dist/types/modules/support/dtos/support-configuration.dto.d.ts +130 -0
- package/dist/types/modules/support/dtos/support-related-entity.dto.d.ts +13 -0
- package/dist/types/modules/support/dtos/support-report-query.dto.d.ts +29 -0
- package/dist/types/modules/support/dtos/support-sync.dto.d.ts +40 -0
- package/dist/types/modules/support/dtos/support-ticket-actions.dto.d.ts +61 -0
- package/dist/types/modules/support/dtos/support-ticket-query.dto.d.ts +41 -0
- package/dist/types/modules/support/enums/support-audit-action.enum.d.ts +80 -0
- package/dist/types/modules/support/enums/support-feedback.enum.d.ts +65 -0
- package/dist/types/modules/support/enums/support-provider-code.enum.d.ts +57 -0
- package/dist/types/modules/support/enums/support-related-entity-type.enum.d.ts +41 -0
- package/dist/types/modules/support/enums/support-routing.enum.d.ts +48 -0
- package/dist/types/modules/support/enums/support-sla.enum.d.ts +47 -0
- package/dist/types/modules/support/enums/support-sync.enum.d.ts +108 -0
- package/dist/types/modules/support/enums/support-ticket-channel.enum.d.ts +30 -0
- package/dist/types/modules/support/enums/support-ticket-message.enum.d.ts +42 -0
- package/dist/types/modules/support/enums/support-ticket-priority.enum.d.ts +24 -0
- package/dist/types/modules/support/enums/support-ticket-status.enum.d.ts +58 -0
- package/dist/types/modules/support/index.d.ts +38 -0
- package/dist/types/modules/support/interfaces/customer-feedback.d.ts +115 -0
- package/dist/types/modules/support/interfaces/support-configuration.d.ts +170 -0
- package/dist/types/modules/support/interfaces/support-events.d.ts +126 -0
- package/dist/types/modules/support/interfaces/support-provider-descriptor.d.ts +92 -0
- package/dist/types/modules/support/interfaces/support-realtime.d.ts +65 -0
- package/dist/types/modules/support/interfaces/support-reports.d.ts +122 -0
- package/dist/types/modules/support/interfaces/support-sync.d.ts +105 -0
- package/dist/types/modules/support/interfaces/support-ticket-message.d.ts +66 -0
- package/dist/types/modules/support/interfaces/support-ticket.d.ts +180 -0
- package/dist/types/modules/support/utils/support-feedback.util.d.ts +23 -0
- package/dist/types/modules/support/utils/support-redaction.util.d.ts +48 -0
- package/dist/types/modules/support/utils/support-routing.util.d.ts +50 -0
- package/dist/types/modules/support/utils/support-sla.util.d.ts +69 -0
- package/dist/types/modules/support/utils/support-status.util.d.ts +44 -0
- package/dist/types/modules/support/utils/support-sync.util.d.ts +76 -0
- package/dist/types/modules/support/utils/support-ticket-number.util.d.ts +39 -0
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { SUPPORT_SYNC_DEFAULTS } from '../constants/support-defaults.const';
|
|
2
|
+
import { PERMANENT_SUPPORT_SYNC_FAILURE_REASONS, SupportSyncFailureReason, } from '../enums/support-sync.enum';
|
|
3
|
+
/**
|
|
4
|
+
* Translate a helpdesk HTTP status into the shared failure taxonomy.
|
|
5
|
+
*
|
|
6
|
+
* The single place the retry policy is decided, because "should we call the
|
|
7
|
+
* helpdesk again?" must not be answered differently by the Zammad adapter and
|
|
8
|
+
* the Freshdesk one. Anything unrecognised is TRANSIENT: a support message that
|
|
9
|
+
* arrives late is recoverable, one dropped because an unfamiliar status looked
|
|
10
|
+
* fatal is not.
|
|
11
|
+
*
|
|
12
|
+
* The one place that reasoning inverts is a 2xx nobody could parse. The
|
|
13
|
+
* provider accepted the request, so re-sending would create a second ticket or
|
|
14
|
+
* show the customer the same reply twice - see UNREADABLE_SUCCESS, which the
|
|
15
|
+
* adapter raises directly rather than through this function.
|
|
16
|
+
*/
|
|
17
|
+
export function classifySupportHttpStatus(status) {
|
|
18
|
+
if (status === undefined)
|
|
19
|
+
return SupportSyncFailureReason.TIMEOUT;
|
|
20
|
+
if (status >= 200 && status < 300)
|
|
21
|
+
return SupportSyncFailureReason.UNREADABLE_SUCCESS;
|
|
22
|
+
if (status === 400 || status === 422)
|
|
23
|
+
return SupportSyncFailureReason.INVALID_PAYLOAD;
|
|
24
|
+
if (status === 401)
|
|
25
|
+
return SupportSyncFailureReason.AUTHENTICATION_FAILED;
|
|
26
|
+
if (status === 403)
|
|
27
|
+
return SupportSyncFailureReason.AUTHORIZATION_FAILED;
|
|
28
|
+
// 404 is TRANSIENT on purpose. A genuinely wrong path exhausts its attempts
|
|
29
|
+
// in a few minutes and costs nothing; a 404 from an ingress mid-deploy is
|
|
30
|
+
// common, and treating that as permanent would silently drop a reply the
|
|
31
|
+
// customer is waiting for.
|
|
32
|
+
if (status === 404)
|
|
33
|
+
return SupportSyncFailureReason.PROVIDER_UNAVAILABLE;
|
|
34
|
+
if (status === 409)
|
|
35
|
+
return SupportSyncFailureReason.PROVIDER_REJECTED;
|
|
36
|
+
if (status === 429)
|
|
37
|
+
return SupportSyncFailureReason.RATE_LIMITED;
|
|
38
|
+
if (status >= 500)
|
|
39
|
+
return SupportSyncFailureReason.PROVIDER_UNAVAILABLE;
|
|
40
|
+
if (status >= 400)
|
|
41
|
+
return SupportSyncFailureReason.PROVIDER_REJECTED;
|
|
42
|
+
return SupportSyncFailureReason.UNKNOWN;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Whether a failure can ever succeed on a retry.
|
|
46
|
+
*
|
|
47
|
+
* AUTHENTICATION_FAILED is deliberately NOT permanent: a rotated credential
|
|
48
|
+
* that has not propagated to every pod yet fails this way, and refusing to try
|
|
49
|
+
* again would strand every queued reply until somebody noticed. It is capped by
|
|
50
|
+
* `maxAttempts` like anything else.
|
|
51
|
+
*/
|
|
52
|
+
export function isPermanentSupportSyncFailure(reason) {
|
|
53
|
+
return PERMANENT_SUPPORT_SYNC_FAILURE_REASONS.includes(reason);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* When to try again, with exponential backoff and jitter.
|
|
57
|
+
*
|
|
58
|
+
* The jitter matters more than it looks: when a helpdesk comes back after an
|
|
59
|
+
* outage, every queued row is due at once, and a synchronized stampede is how a
|
|
60
|
+
* recovering server is knocked over a second time.
|
|
61
|
+
*
|
|
62
|
+
* `randomFraction` is injected rather than read from Math.random so the
|
|
63
|
+
* function stays pure and its tests stay deterministic.
|
|
64
|
+
*/
|
|
65
|
+
export function computeSupportRetryDelaySeconds(attempts, options = {}) {
|
|
66
|
+
var _a, _b, _c, _d;
|
|
67
|
+
const base = (_a = options.baseSeconds) !== null && _a !== void 0 ? _a : SUPPORT_SYNC_DEFAULTS.RETRY_BASE_SECONDS;
|
|
68
|
+
const max = (_b = options.maxSeconds) !== null && _b !== void 0 ? _b : SUPPORT_SYNC_DEFAULTS.RETRY_MAX_SECONDS;
|
|
69
|
+
const jitterRatio = (_c = options.jitterRatio) !== null && _c !== void 0 ? _c : SUPPORT_SYNC_DEFAULTS.RETRY_JITTER_RATIO;
|
|
70
|
+
const randomFraction = (_d = options.randomFraction) !== null && _d !== void 0 ? _d : 0;
|
|
71
|
+
const exponent = Math.max(0, attempts - 1);
|
|
72
|
+
const raw = base * Math.pow(2, Math.min(exponent, 16));
|
|
73
|
+
let delay = Math.min(max, raw);
|
|
74
|
+
// A provider that says when to come back is obeyed, so long as it is not
|
|
75
|
+
// asking for longer than the ceiling.
|
|
76
|
+
if (options.retryAfterSeconds != null && options.retryAfterSeconds > 0) {
|
|
77
|
+
delay = Math.min(max, Math.max(delay, options.retryAfterSeconds));
|
|
78
|
+
}
|
|
79
|
+
const jitter = delay * jitterRatio * randomFraction;
|
|
80
|
+
return Math.round(delay + jitter);
|
|
81
|
+
}
|
|
82
|
+
/** The instant of the next attempt. */
|
|
83
|
+
export function computeSupportNextAttemptAt(now, attempts, options) {
|
|
84
|
+
return new Date(now.getTime() + computeSupportRetryDelaySeconds(attempts, options) * 1000);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A stable fingerprint of an outbound payload.
|
|
88
|
+
*
|
|
89
|
+
* Deliberately not cryptographic. It exists to answer "is this the same request
|
|
90
|
+
* we already sent?" and to let a reconciliation job tell "never sent" from
|
|
91
|
+
* "sent and did not take" - neither of which is a security decision. Using a
|
|
92
|
+
* real digest here would pull a Node-only dependency into a package the
|
|
93
|
+
* frontend build also consumes.
|
|
94
|
+
*/
|
|
95
|
+
export function fingerprintSupportPayload(payload) {
|
|
96
|
+
const serialized = stableStringify(payload);
|
|
97
|
+
let hash = 5381;
|
|
98
|
+
for (let index = 0; index < serialized.length; index += 1) {
|
|
99
|
+
hash = ((hash << 5) + hash + serialized.charCodeAt(index)) | 0;
|
|
100
|
+
}
|
|
101
|
+
return `${(hash >>> 0).toString(16)}-${serialized.length.toString(16)}`;
|
|
102
|
+
}
|
|
103
|
+
/** JSON with object keys in a fixed order, so two equal payloads fingerprint alike. */
|
|
104
|
+
function stableStringify(value) {
|
|
105
|
+
var _a;
|
|
106
|
+
if (value === null || typeof value !== 'object')
|
|
107
|
+
return (_a = JSON.stringify(value)) !== null && _a !== void 0 ? _a : 'null';
|
|
108
|
+
if (Array.isArray(value))
|
|
109
|
+
return `[${value.map(stableStringify).join(',')}]`;
|
|
110
|
+
const source = value;
|
|
111
|
+
const keys = Object.keys(source).sort();
|
|
112
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${stableStringify(source[key])}`).join(',')}}`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether an outbound call may proceed.
|
|
116
|
+
*
|
|
117
|
+
* The breaker protects the helpdesk and this service's own worker from
|
|
118
|
+
* hammering a dead endpoint; it never causes data loss, because a call refused
|
|
119
|
+
* by an open breaker leaves its row PENDING with a CIRCUIT_OPEN reason and is
|
|
120
|
+
* retried when the breaker closes.
|
|
121
|
+
*/
|
|
122
|
+
export function isSupportCircuitOpen(state, now) {
|
|
123
|
+
if (!(state === null || state === void 0 ? void 0 : state.openUntil))
|
|
124
|
+
return false;
|
|
125
|
+
return new Date(state.openUntil).getTime() > now.getTime();
|
|
126
|
+
}
|
|
127
|
+
/** The breaker state after one outcome. */
|
|
128
|
+
export function nextSupportCircuitState(state, outcome, now, options = {}) {
|
|
129
|
+
var _a, _b, _c;
|
|
130
|
+
const threshold = (_a = options.failureThreshold) !== null && _a !== void 0 ? _a : SUPPORT_SYNC_DEFAULTS.CIRCUIT_FAILURE_THRESHOLD;
|
|
131
|
+
const openSeconds = (_b = options.openSeconds) !== null && _b !== void 0 ? _b : SUPPORT_SYNC_DEFAULTS.CIRCUIT_OPEN_SECONDS;
|
|
132
|
+
if (outcome === 'success')
|
|
133
|
+
return { consecutiveFailures: 0, openUntil: null };
|
|
134
|
+
const consecutiveFailures = ((_c = state === null || state === void 0 ? void 0 : state.consecutiveFailures) !== null && _c !== void 0 ? _c : 0) + 1;
|
|
135
|
+
if (consecutiveFailures < threshold)
|
|
136
|
+
return { consecutiveFailures, openUntil: null };
|
|
137
|
+
return {
|
|
138
|
+
consecutiveFailures,
|
|
139
|
+
openUntil: new Date(now.getTime() + openSeconds * 1000).toISOString(),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=support-sync.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-sync.util.js","sourceRoot":"","sources":["../../../../../src/modules/support/utils/support-sync.util.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SUPPORT_TICKET_NUMBER_PREFIX, SUPPORT_TICKET_NUMBER_SEQUENCE_WIDTH, } from '../constants/support-defaults.const';
|
|
2
|
+
/**
|
|
3
|
+
* Render a ticket number: SUP-KE-2026-000123.
|
|
4
|
+
*
|
|
5
|
+
* Human-readable and safe to read out over the phone, which is the whole point
|
|
6
|
+
* of it existing alongside the uuid primary key. It is never the primary key:
|
|
7
|
+
* it embeds a country and a year, and anything that embeds business meaning
|
|
8
|
+
* will eventually need changing.
|
|
9
|
+
*
|
|
10
|
+
* The sequence is allocated per (country, year) by the database, so this
|
|
11
|
+
* function only formats - it never decides what the next number is.
|
|
12
|
+
*/
|
|
13
|
+
export function formatSupportTicketNumber(countryCode, year, sequence) {
|
|
14
|
+
const padded = String(Math.max(0, Math.trunc(sequence))).padStart(SUPPORT_TICKET_NUMBER_SEQUENCE_WIDTH, '0');
|
|
15
|
+
return `${SUPPORT_TICKET_NUMBER_PREFIX}-${countryCode}-${year}-${padded}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Read a ticket number back, for search.
|
|
19
|
+
*
|
|
20
|
+
* Returns null rather than throwing on anything unrecognised: this runs on a
|
|
21
|
+
* search box, where the input is whatever somebody pasted, and a 500 from a bad
|
|
22
|
+
* paste is a worse answer than no results.
|
|
23
|
+
*
|
|
24
|
+
* A sequence longer than the configured width still parses - the width is a
|
|
25
|
+
* display minimum, and refusing to find ticket 1,000,000 because it has seven
|
|
26
|
+
* digits would be a bug that only appears once it is too late.
|
|
27
|
+
*/
|
|
28
|
+
export function parseSupportTicketNumber(value) {
|
|
29
|
+
if (value == null)
|
|
30
|
+
return null;
|
|
31
|
+
const raw = String(value).trim().toUpperCase();
|
|
32
|
+
const match = /^([A-Z]{2,5})-([A-Z]{2})-(\d{4})-(\d{1,12})$/.exec(raw);
|
|
33
|
+
if (!match)
|
|
34
|
+
return null;
|
|
35
|
+
const [, prefix, country, year, sequence] = match;
|
|
36
|
+
if (prefix !== SUPPORT_TICKET_NUMBER_PREFIX)
|
|
37
|
+
return null;
|
|
38
|
+
return {
|
|
39
|
+
prefix,
|
|
40
|
+
countryCode: country,
|
|
41
|
+
year: Number(year),
|
|
42
|
+
sequence: Number(sequence),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Whether a search term looks like somebody typing a ticket number.
|
|
47
|
+
*
|
|
48
|
+
* Used to route a search straight at the ticket-number index instead of running
|
|
49
|
+
* a full-text scan for a string that can only ever match one row.
|
|
50
|
+
*/
|
|
51
|
+
export function looksLikeSupportTicketNumber(value) {
|
|
52
|
+
if (value == null)
|
|
53
|
+
return false;
|
|
54
|
+
return /^SUP-/i.test(String(value).trim());
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=support-ticket-number.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"support-ticket-number.util.js","sourceRoot":"","sources":["../../../../../src/modules/support/utils/support-ticket-number.util.ts"],"names":[],"mappings":"AACA,OAAO,EACH,4BAA4B,EAC5B,oCAAoC,GACvC,MAAM,qCAAqC,CAAC;AAU7C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,yBAAyB,CACrC,WAAwB,EACxB,IAAY,EACZ,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAC7D,oCAAoC,EACpC,GAAG,CACN,CAAC;IACF,OAAO,GAAG,4BAA4B,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;AAC9E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAgC;IACrE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/C,MAAM,KAAK,GAAG,8CAA8C,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IAExB,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC;IAClD,IAAI,MAAM,KAAK,4BAA4B;QAAE,OAAO,IAAI,CAAC;IAEzD,OAAO;QACH,MAAM;QACN,WAAW,EAAE,OAAsB;QACnC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;KAC7B,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,KAAgC;IACzE,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,KAAK,CAAC;IAChC,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export * from './modules/entitlement/index';
|
|
|
23
23
|
export * from './modules/alert-dispatch/index';
|
|
24
24
|
export * from './modules/system-user/index';
|
|
25
25
|
export * from './modules/partner/index';
|
|
26
|
+
export * from './modules/support/index';
|
|
26
27
|
export * from './interfaces/server-message';
|
|
27
28
|
export * from './interfaces/i-request-with-user';
|
|
28
29
|
export * from './interfaces/validated-user';
|
|
@@ -55,4 +55,25 @@ export declare const KAFKA_TOPICS: {
|
|
|
55
55
|
ORG_RESPONSE_UNIT_STATUS_CHANGED: string;
|
|
56
56
|
PARTNER_DISPATCH_CREATED: string;
|
|
57
57
|
PARTNER_DISPATCH_STATUS_CHANGED: string;
|
|
58
|
+
SUPPORT_TICKET_CREATED: string;
|
|
59
|
+
SUPPORT_TICKET_UPDATED: string;
|
|
60
|
+
SUPPORT_TICKET_ASSIGNED: string;
|
|
61
|
+
SUPPORT_TICKET_STATUS_CHANGED: string;
|
|
62
|
+
SUPPORT_TICKET_PRIORITY_CHANGED: string;
|
|
63
|
+
SUPPORT_TICKET_MESSAGE_CREATED: string;
|
|
64
|
+
SUPPORT_TICKET_CUSTOMER_REPLIED: string;
|
|
65
|
+
SUPPORT_TICKET_AGENT_REPLIED: string;
|
|
66
|
+
SUPPORT_TICKET_RESOLVED: string;
|
|
67
|
+
SUPPORT_TICKET_CLOSED: string;
|
|
68
|
+
SUPPORT_TICKET_REOPENED: string;
|
|
69
|
+
SUPPORT_TICKET_SLA_WARNING: string;
|
|
70
|
+
SUPPORT_TICKET_SLA_BREACHED: string;
|
|
71
|
+
SUPPORT_FEEDBACK_CREATED: string;
|
|
72
|
+
SUPPORT_FEEDBACK_UPDATED: string;
|
|
73
|
+
SUPPORT_FEEDBACK_REVIEWED: string;
|
|
74
|
+
SUPPORT_FEEDBACK_RESPONDED: string;
|
|
75
|
+
SUPPORT_FEEDBACK_CONVERTED_TO_TICKET: string;
|
|
76
|
+
SUPPORT_FEEDBACK_RATING_SUBMITTED: string;
|
|
77
|
+
SUPPORT_PROVIDER_SYNC_FAILED: string;
|
|
78
|
+
SUPPORT_PROVIDER_SYNC_RECOVERED: string;
|
|
58
79
|
};
|
|
@@ -14,6 +14,27 @@ export declare enum PermissionActions {
|
|
|
14
14
|
RESEND_PARTNER_DISPATCH = "resend:partner-dispatch",
|
|
15
15
|
READ_PARTNER_MEMBERSHIP = "read:partner-membership",
|
|
16
16
|
MANAGE_PARTNER_MEMBERSHIP = "manage:partner-membership",
|
|
17
|
+
CREATE_SUPPORT_TICKET = "create:support-ticket",
|
|
18
|
+
READ_SUPPORT_TICKET = "read:support-ticket",
|
|
19
|
+
UPDATE_SUPPORT_TICKET = "update:support-ticket",
|
|
20
|
+
ASSIGN_SUPPORT_TICKET = "assign:support-ticket",
|
|
21
|
+
REPLY_SUPPORT_TICKET = "reply:support-ticket",
|
|
22
|
+
NOTE_SUPPORT_TICKET = "note:support-ticket",
|
|
23
|
+
CHANGE_STATUS_SUPPORT_TICKET = "change-status:support-ticket",
|
|
24
|
+
CHANGE_PRIORITY_SUPPORT_TICKET = "change-priority:support-ticket",
|
|
25
|
+
CLOSE_SUPPORT_TICKET = "close:support-ticket",
|
|
26
|
+
REOPEN_SUPPORT_TICKET = "reopen:support-ticket",
|
|
27
|
+
READ_SUPPORT_FEEDBACK = "read:support-feedback",
|
|
28
|
+
REVIEW_SUPPORT_FEEDBACK = "review:support-feedback",
|
|
29
|
+
RESPOND_SUPPORT_FEEDBACK = "respond:support-feedback",
|
|
30
|
+
CONVERT_SUPPORT_FEEDBACK = "convert:support-feedback",
|
|
31
|
+
MANAGE_SUPPORT_QUEUE = "manage:support-queue",
|
|
32
|
+
MANAGE_SUPPORT_TEAM = "manage:support-team",
|
|
33
|
+
MANAGE_SUPPORT_SLA = "manage:support-sla",
|
|
34
|
+
MANAGE_SUPPORT_CONFIGURATION = "manage:support-configuration",
|
|
35
|
+
READ_SUPPORT_REPORT = "read:support-report",
|
|
36
|
+
READ_SUPPORT_SYNC = "read:support-sync",
|
|
37
|
+
MANAGE_SUPPORT_SYNC = "manage:support-sync",
|
|
17
38
|
CREATE_CONTROL_CENTRE = "create:control-centre",
|
|
18
39
|
READ_CONTROL_CENTRE = "read:control-centre",
|
|
19
40
|
UPDATE_CONTROL_CENTRE = "update:control-centre",
|
|
@@ -9,5 +9,13 @@ export declare enum RoomTypeEnum {
|
|
|
9
9
|
* like count updates.
|
|
10
10
|
*/
|
|
11
11
|
POST = "post",
|
|
12
|
+
/**
|
|
13
|
+
* Support rooms use a two-part scheme under one prefix
|
|
14
|
+
* (support:ticket:{uuid}, support:queue:{uuid}, support:user:{id},
|
|
15
|
+
* support:org:{id}) and their own authorization, so they are matched by
|
|
16
|
+
* prefix rather than through this enum. Declared here so the prefix is
|
|
17
|
+
* registered in one place.
|
|
18
|
+
*/
|
|
19
|
+
SUPPORT = "support",
|
|
12
20
|
INVALID = "invalid"
|
|
13
21
|
}
|
|
@@ -8,5 +8,6 @@ export declare enum SocketEventName {
|
|
|
8
8
|
TRACKING_POSITION = "tracking:position",
|
|
9
9
|
TRACKING_STATUS = "tracking:status",
|
|
10
10
|
TRACKING_REMOVED = "tracking:removed",
|
|
11
|
-
TRACKING_PROVIDER_HEALTH = "tracking:provider-health"
|
|
11
|
+
TRACKING_PROVIDER_HEALTH = "tracking:provider-health",
|
|
12
|
+
SUPPORT_EVENT = "support.event"
|
|
12
13
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { SupportSlaClock } from '../enums/support-sla.enum';
|
|
2
|
+
import { SupportTicketPriority } from '../enums/support-ticket-priority.enum';
|
|
3
|
+
/**
|
|
4
|
+
* One SLA row: how long a first response and a resolution may take, and whether
|
|
5
|
+
* the clock runs around the clock or only in working hours.
|
|
6
|
+
*/
|
|
7
|
+
export interface SupportSlaTargetDefaults {
|
|
8
|
+
/** Minutes allowed for the first agent reply. */
|
|
9
|
+
firstResponseMinutes: number;
|
|
10
|
+
/** Minutes allowed to reach RESOLVED. */
|
|
11
|
+
resolutionMinutes: number;
|
|
12
|
+
/**
|
|
13
|
+
* CALENDAR runs continuously; BUSINESS consumes only working minutes.
|
|
14
|
+
*
|
|
15
|
+
* The split matters at the edges. A CRITICAL ticket must be answered at 03:00
|
|
16
|
+
* on a Sunday, because an emergency platform that is down is down. A NORMAL
|
|
17
|
+
* ticket raised at 17:00 on a Friday must not be reported as breached before
|
|
18
|
+
* anybody is back at a desk - that is how a support team learns to ignore the
|
|
19
|
+
* breach column.
|
|
20
|
+
*/
|
|
21
|
+
clock: SupportSlaClock;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The platform's default SLA matrix.
|
|
25
|
+
*
|
|
26
|
+
* These are DEFAULTS, not business rules. An organization-level policy overrides
|
|
27
|
+
* them, a queue-level policy overrides that, and both are stored data an
|
|
28
|
+
* administrator edits. Nothing in the SLA engine reads a hard-coded number.
|
|
29
|
+
*
|
|
30
|
+
* Business figures are expressed in working minutes and resolved against the
|
|
31
|
+
* country's calendar: 8 business hours = 480, 1 business day = 480, 3 business
|
|
32
|
+
* days = 1440, 5 business days = 2400.
|
|
33
|
+
*/
|
|
34
|
+
export declare const SUPPORT_SLA_DEFAULTS: Readonly<Record<SupportTicketPriority, SupportSlaTargetDefaults>>;
|
|
35
|
+
/**
|
|
36
|
+
* The working calendar an organization inherits when it has not defined its own.
|
|
37
|
+
*
|
|
38
|
+
* Monday to Friday, 08:00-17:00 local. `timezone` is resolved from the ticket's
|
|
39
|
+
* country rather than from the server, so a Kampala ticket is measured in
|
|
40
|
+
* Kampala hours; every supported country happens to sit in the same offset
|
|
41
|
+
* today, and writing it this way is what stops that being an assumption.
|
|
42
|
+
*/
|
|
43
|
+
export declare const SUPPORT_BUSINESS_CALENDAR_DEFAULTS: {
|
|
44
|
+
/** ISO weekday numbers, Monday = 1. */
|
|
45
|
+
readonly workingDays: readonly number[];
|
|
46
|
+
/** Minutes past local midnight when the working day opens. */
|
|
47
|
+
readonly startMinuteOfDay: number;
|
|
48
|
+
/** Minutes past local midnight when it closes. */
|
|
49
|
+
readonly endMinuteOfDay: number;
|
|
50
|
+
/** Working minutes in one day, derived - kept here so callers need not recompute. */
|
|
51
|
+
readonly minutesPerWorkingDay: number;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* When a ticket starts showing as WARNING rather than ON_TRACK.
|
|
55
|
+
*
|
|
56
|
+
* 80% of the way to the deadline. Expressed as a fraction rather than a fixed
|
|
57
|
+
* lead time because a fixed one is meaningless across a matrix that spans
|
|
58
|
+
* fifteen minutes to five days.
|
|
59
|
+
*/
|
|
60
|
+
export declare const SUPPORT_SLA_WARNING_THRESHOLD_RATIO = 0.8;
|
|
61
|
+
/**
|
|
62
|
+
* How long after RESOLVED a ticket closes itself when the customer says nothing.
|
|
63
|
+
*
|
|
64
|
+
* A resolved ticket that nobody closes is invisible work: it stays out of the
|
|
65
|
+
* open counts but keeps its conversation open forever. Auto-closing is
|
|
66
|
+
* reversible - the customer can still reopen - which is why it is safe to do at
|
|
67
|
+
* all.
|
|
68
|
+
*/
|
|
69
|
+
export declare const SUPPORT_AUTO_CLOSE_RESOLVED_AFTER_HOURS = 72;
|
|
70
|
+
/** Provider synchronization behaviour. Every value is overridable per deployment. */
|
|
71
|
+
export declare const SUPPORT_SYNC_DEFAULTS: {
|
|
72
|
+
/** Attempts, including the first, before a transient failure is dead-lettered. */
|
|
73
|
+
readonly MAX_ATTEMPTS: 8;
|
|
74
|
+
/** Base of the exponential backoff, in seconds: 20s, 40s, 80s, ... */
|
|
75
|
+
readonly RETRY_BASE_SECONDS: 20;
|
|
76
|
+
/** Ceiling for the backoff, in seconds. */
|
|
77
|
+
readonly RETRY_MAX_SECONDS: 3600;
|
|
78
|
+
/** Jitter added to each retry delay, as a fraction of the delay. */
|
|
79
|
+
readonly RETRY_JITTER_RATIO: 0.2;
|
|
80
|
+
/** Per-request timeout for an outbound helpdesk call, in milliseconds. */
|
|
81
|
+
readonly REQUEST_TIMEOUT_MS: 15000;
|
|
82
|
+
/** Rows a worker claims per tick. */
|
|
83
|
+
readonly BATCH_SIZE: 25;
|
|
84
|
+
/** How long a row may sit IN_PROGRESS before it is treated as abandoned, in minutes. */
|
|
85
|
+
readonly STUCK_IN_PROGRESS_MINUTES: 10;
|
|
86
|
+
/** Consecutive provider failures that trip the circuit breaker. */
|
|
87
|
+
readonly CIRCUIT_FAILURE_THRESHOLD: 5;
|
|
88
|
+
/** How long the breaker stays open before a single probe is allowed, in seconds. */
|
|
89
|
+
readonly CIRCUIT_OPEN_SECONDS: 60;
|
|
90
|
+
/** Longest a webhook delivery record is kept for replay detection, in hours. */
|
|
91
|
+
readonly WEBHOOK_DEDUP_TTL_HOURS: 48;
|
|
92
|
+
};
|
|
93
|
+
/** Field limits applied before anything is sent to a helpdesk or stored. */
|
|
94
|
+
export declare const SUPPORT_FIELD_LIMITS: {
|
|
95
|
+
readonly SUBJECT_MAX_LENGTH: 200;
|
|
96
|
+
readonly DESCRIPTION_MAX_LENGTH: 20000;
|
|
97
|
+
readonly MESSAGE_MAX_LENGTH: 20000;
|
|
98
|
+
readonly FEEDBACK_TITLE_MAX_LENGTH: 200;
|
|
99
|
+
readonly FEEDBACK_MESSAGE_MAX_LENGTH: 5000;
|
|
100
|
+
readonly TAG_MAX_LENGTH: 50;
|
|
101
|
+
readonly MAX_TAGS_PER_TICKET: 20;
|
|
102
|
+
readonly MAX_ATTACHMENTS_PER_MESSAGE: 10;
|
|
103
|
+
/** Longest error text persisted on a synchronization row. */
|
|
104
|
+
readonly SYNC_ERROR_MAX_LENGTH: 2000;
|
|
105
|
+
/** Longest provider payload snapshot kept on a synchronization row. */
|
|
106
|
+
readonly SYNC_SNAPSHOT_MAX_LENGTH: 8000;
|
|
107
|
+
};
|
|
108
|
+
/** Rating bounds for the feedback types that carry one. */
|
|
109
|
+
export declare const SUPPORT_FEEDBACK_RATING: {
|
|
110
|
+
readonly MIN: 1;
|
|
111
|
+
readonly MAX: 5;
|
|
112
|
+
/** At or below this, a rating counts as negative for sentiment. */
|
|
113
|
+
readonly NEGATIVE_AT_OR_BELOW: 2;
|
|
114
|
+
/** At or above this, a rating counts as positive. */
|
|
115
|
+
readonly POSITIVE_AT_OR_ABOVE: 4;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Header carrying a client-supplied idempotency key.
|
|
119
|
+
*
|
|
120
|
+
* Mobile networks drop replies, not requests. Without this a customer who taps
|
|
121
|
+
* Send twice on a train raises two tickets, and the second one wastes an
|
|
122
|
+
* agent's time proving it is a duplicate of the first.
|
|
123
|
+
*/
|
|
124
|
+
export declare const SUPPORT_IDEMPOTENCY_HEADER = "idempotency-key";
|
|
125
|
+
/** How long an idempotency key is honoured. Long enough to cover any real retry. */
|
|
126
|
+
export declare const SUPPORT_IDEMPOTENCY_TTL_HOURS = 24;
|
|
127
|
+
/** Ticket-number format: SUP-<COUNTRY>-<YEAR>-<6-digit sequence>. */
|
|
128
|
+
export declare const SUPPORT_TICKET_NUMBER_PREFIX = "SUP";
|
|
129
|
+
export declare const SUPPORT_TICKET_NUMBER_SEQUENCE_WIDTH = 6;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consumer groups for the support topics. One group per logical consumer, so
|
|
3
|
+
* adding a consumer never steals another's messages.
|
|
4
|
+
*/
|
|
5
|
+
export declare const SUPPORT_CONSUMER_GROUPS: {
|
|
6
|
+
/** clarion-notification: tells a customer an agent replied, and a supervisor that an SLA slipped. */
|
|
7
|
+
readonly NOTIFICATION: "support-notification";
|
|
8
|
+
/** clarion-socket: keeps the admin console and the customer's ticket screen live. */
|
|
9
|
+
readonly REALTIME: "support-realtime";
|
|
10
|
+
/** Anything analytical that wants the raw stream. */
|
|
11
|
+
readonly ANALYTICS: "support-analytics";
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Redis channel clarion-support publishes live ticket and feedback updates on,
|
|
15
|
+
* mirroring the newsfeed and tracking realtime bridges that clarion-socket
|
|
16
|
+
* already subscribes to.
|
|
17
|
+
*
|
|
18
|
+
* Redis rather than Kafka for the live path, deliberately: clarion-socket
|
|
19
|
+
* consumes Redis pub/sub for every other domain, and a second transport into
|
|
20
|
+
* the same service would be a new failure mode for no benefit. Kafka carries
|
|
21
|
+
* the durable, replayable record of the same facts.
|
|
22
|
+
*/
|
|
23
|
+
export declare const SUPPORT_REALTIME_CHANNEL = "realtime:support";
|
|
24
|
+
/**
|
|
25
|
+
* Room names clients subscribe to for live support updates.
|
|
26
|
+
*
|
|
27
|
+
* A customer joins only their own ticket's room; an agent joins a queue room
|
|
28
|
+
* and their own user room. The authorization for each is enforced in
|
|
29
|
+
* clarion-socket, not here - these helpers exist so producer and consumer
|
|
30
|
+
* cannot drift on the string format.
|
|
31
|
+
*/
|
|
32
|
+
export declare const SUPPORT_ROOMS: {
|
|
33
|
+
readonly ticket: (ticketId: string) => string;
|
|
34
|
+
readonly queue: (queueId: string) => string;
|
|
35
|
+
readonly user: (userId: number | string) => string;
|
|
36
|
+
readonly organization: (organizationId: number | string) => string;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* How long a consumed provider webhook is remembered, to collapse redeliveries.
|
|
40
|
+
*
|
|
41
|
+
* Helpdesks retry a delivery whose acknowledgement they did not see, and a
|
|
42
|
+
* replayed reply would be shown to the customer twice. The row is the record of
|
|
43
|
+
* record; this constant only bounds how long it is consulted.
|
|
44
|
+
*/
|
|
45
|
+
export declare const SUPPORT_WEBHOOK_EVENT_DEDUP_TTL_SECONDS: number;
|
|
46
|
+
/** Dedup namespace used when claiming a support event id in Redis. */
|
|
47
|
+
export declare const SUPPORT_EVENT_DEDUP_NAMESPACE = "support.events";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Add a message to a ticket conversation.
|
|
3
|
+
*
|
|
4
|
+
* There is deliberately no `type` field. Whether an entry is a customer message
|
|
5
|
+
* or an agent reply is decided by clarion-support from the caller's identity
|
|
6
|
+
* and permissions, never by the client - a customer able to post an
|
|
7
|
+
* AGENT_REPLY, or an agent able to post an internal note through the
|
|
8
|
+
* customer-facing endpoint, would each be a security bug rather than a
|
|
9
|
+
* validation one.
|
|
10
|
+
*
|
|
11
|
+
* Internal notes have their own endpoint and their own permission for the same
|
|
12
|
+
* reason.
|
|
13
|
+
*/
|
|
14
|
+
export declare class CreateSupportTicketMessageDto {
|
|
15
|
+
body: string;
|
|
16
|
+
documentIds?: number[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Add an internal note.
|
|
20
|
+
*
|
|
21
|
+
* Never mirrored to a customer and never returned by a customer-facing
|
|
22
|
+
* endpoint. It IS pushed to the helpdesk as a note where the provider supports
|
|
23
|
+
* one, because an agent working in the helpdesk needs the same context - which
|
|
24
|
+
* is exactly why the visibility rule has to live in the domain rather than in
|
|
25
|
+
* whichever adapter happens to be configured.
|
|
26
|
+
*/
|
|
27
|
+
export declare class CreateSupportInternalNoteDto {
|
|
28
|
+
body: string;
|
|
29
|
+
documentIds?: number[];
|
|
30
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { CountryCode } from '../../country/enums/country-code.enum';
|
|
2
|
+
import { IncidentAppId } from '../../incident/enums/incident-app-id.enum';
|
|
3
|
+
import { SupportTicketChannel } from '../enums/support-ticket-channel.enum';
|
|
4
|
+
import { SupportTicketPriority } from '../enums/support-ticket-priority.enum';
|
|
5
|
+
import { SupportRelatedEntityDto } from './support-related-entity.dto';
|
|
6
|
+
/**
|
|
7
|
+
* Raise a support ticket.
|
|
8
|
+
*
|
|
9
|
+
* Tenancy is NOT taken from this payload. `organizationId`, `controlCentreId`
|
|
10
|
+
* and the customer are resolved from the caller's trusted context in
|
|
11
|
+
* clarion-support; the two overridable fields below are honoured only for a
|
|
12
|
+
* super-admin or an agent raising a ticket on somebody's behalf, and are
|
|
13
|
+
* ignored for everyone else. A customer who sends another organization's id
|
|
14
|
+
* still gets a ticket in their own.
|
|
15
|
+
*
|
|
16
|
+
* Retries are safe: send the same `Idempotency-Key` header and a repeat is
|
|
17
|
+
* answered with the ticket the first attempt created. Mobile networks drop
|
|
18
|
+
* replies rather than requests, and without that a customer who taps Send twice
|
|
19
|
+
* on a train raises two tickets.
|
|
20
|
+
*/
|
|
21
|
+
export declare class CreateSupportTicketDto {
|
|
22
|
+
subject: string;
|
|
23
|
+
description: string;
|
|
24
|
+
categoryId?: string;
|
|
25
|
+
priority?: SupportTicketPriority;
|
|
26
|
+
channel?: SupportTicketChannel;
|
|
27
|
+
relatedEntities?: SupportRelatedEntityDto[];
|
|
28
|
+
documentIds?: number[];
|
|
29
|
+
tags?: string[];
|
|
30
|
+
appId?: IncidentAppId;
|
|
31
|
+
countryCode?: CountryCode;
|
|
32
|
+
organizationId?: number;
|
|
33
|
+
customerUserId?: number;
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { CountryCode } from '../../country/enums/country-code.enum';
|
|
2
|
+
import { IncidentAppId } from '../../incident/enums/incident-app-id.enum';
|
|
3
|
+
import { CustomerFeedbackChannel, CustomerFeedbackSentiment, CustomerFeedbackStatus, CustomerFeedbackType } from '../enums/support-feedback.enum';
|
|
4
|
+
import { SupportTicketPriority } from '../enums/support-ticket-priority.enum';
|
|
5
|
+
import { SupportRelatedEntityDto } from './support-related-entity.dto';
|
|
6
|
+
/**
|
|
7
|
+
* Diagnostic context a client may send with feedback.
|
|
8
|
+
*
|
|
9
|
+
* This list is a closed allowlist, not a suggestion. Anything a client sends
|
|
10
|
+
* that is not declared here is stripped by the global validation pipe, which is
|
|
11
|
+
* what stops "just send the whole failing request, it would be so useful"
|
|
12
|
+
* putting an access token in a table a wide group of people can read.
|
|
13
|
+
*/
|
|
14
|
+
export declare class CustomerFeedbackContextDto {
|
|
15
|
+
appId?: IncidentAppId;
|
|
16
|
+
appVersion?: string;
|
|
17
|
+
platform?: string;
|
|
18
|
+
osVersion?: string;
|
|
19
|
+
deviceModel?: string;
|
|
20
|
+
screen?: string;
|
|
21
|
+
locale?: string;
|
|
22
|
+
correlationId?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Submit a piece of feedback. Idempotent on the `Idempotency-Key` header, like a ticket. */
|
|
25
|
+
export declare class CreateCustomerFeedbackDto {
|
|
26
|
+
type: CustomerFeedbackType;
|
|
27
|
+
title?: string;
|
|
28
|
+
message: string;
|
|
29
|
+
rating?: number;
|
|
30
|
+
channel?: CustomerFeedbackChannel;
|
|
31
|
+
relatedEntities?: SupportRelatedEntityDto[];
|
|
32
|
+
context?: CustomerFeedbackContextDto;
|
|
33
|
+
organizationId?: number;
|
|
34
|
+
countryCode?: CountryCode;
|
|
35
|
+
}
|
|
36
|
+
/** Reply to a customer's feedback. Moves it to RESPONDED and notifies them. */
|
|
37
|
+
export declare class RespondToCustomerFeedbackDto {
|
|
38
|
+
body: string;
|
|
39
|
+
}
|
|
40
|
+
/** Move a piece of feedback through its review workflow. */
|
|
41
|
+
export declare class UpdateCustomerFeedbackStatusDto {
|
|
42
|
+
status: CustomerFeedbackStatus;
|
|
43
|
+
reason?: string;
|
|
44
|
+
sentiment?: CustomerFeedbackSentiment;
|
|
45
|
+
tags?: string[];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Promote a piece of feedback into a ticket.
|
|
49
|
+
*
|
|
50
|
+
* The two records stay separate for good: the feedback keeps its own lifecycle
|
|
51
|
+
* and its own analytics, and gains a `convertedTicketId`. Merging them would
|
|
52
|
+
* lose the fact that somebody chose to escalate, which is the most interesting
|
|
53
|
+
* thing about the pair.
|
|
54
|
+
*/
|
|
55
|
+
export declare class ConvertFeedbackToTicketDto {
|
|
56
|
+
subject?: string;
|
|
57
|
+
priority?: SupportTicketPriority;
|
|
58
|
+
categoryId?: string;
|
|
59
|
+
queueId?: string;
|
|
60
|
+
internalNote?: string;
|
|
61
|
+
}
|
|
62
|
+
/** Filters for a feedback list. Narrows only; never widens the caller's scope. */
|
|
63
|
+
export declare class CustomerFeedbackQueryDto {
|
|
64
|
+
page?: number;
|
|
65
|
+
limit?: number;
|
|
66
|
+
search?: string;
|
|
67
|
+
sortBy?: string;
|
|
68
|
+
sortOrder?: 'ASC' | 'DESC';
|
|
69
|
+
type?: CustomerFeedbackType;
|
|
70
|
+
status?: CustomerFeedbackStatus;
|
|
71
|
+
sentiment?: CustomerFeedbackSentiment;
|
|
72
|
+
channel?: CustomerFeedbackChannel;
|
|
73
|
+
countryCode?: CountryCode;
|
|
74
|
+
organizationId?: number;
|
|
75
|
+
appId?: IncidentAppId;
|
|
76
|
+
appVersion?: string;
|
|
77
|
+
platform?: string;
|
|
78
|
+
maxRating?: number;
|
|
79
|
+
convertedOnly?: boolean;
|
|
80
|
+
openOnly?: boolean;
|
|
81
|
+
from?: string;
|
|
82
|
+
to?: string;
|
|
83
|
+
}
|