grm-shared-library 1.1.221 → 1.1.222

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/dist/cjs/index.js +1 -0
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/kafka/topics.js +10 -1
  4. package/dist/cjs/kafka/topics.js.map +1 -1
  5. package/dist/cjs/modules/alert-dispatch/dtos/guardian-audience.dto.js +41 -0
  6. package/dist/cjs/modules/alert-dispatch/dtos/guardian-audience.dto.js.map +1 -0
  7. package/dist/cjs/modules/alert-dispatch/index.js +4 -0
  8. package/dist/cjs/modules/alert-dispatch/index.js.map +1 -1
  9. package/dist/cjs/modules/alert-dispatch/interfaces/guardian-audience.js +3 -0
  10. package/dist/cjs/modules/alert-dispatch/interfaces/guardian-audience.js.map +1 -0
  11. package/dist/cjs/modules/alert-dispatch/utils/guardian-audience.util.js +63 -0
  12. package/dist/cjs/modules/alert-dispatch/utils/guardian-audience.util.js.map +1 -0
  13. package/dist/cjs/modules/common/constants/service.const.js +1 -0
  14. package/dist/cjs/modules/common/constants/service.const.js.map +1 -1
  15. package/dist/cjs/modules/gis/dtos/private-trip.dto.js +180 -0
  16. package/dist/cjs/modules/gis/dtos/private-trip.dto.js.map +1 -0
  17. package/dist/cjs/modules/gis/enums/trip-privacy.enum.js +28 -0
  18. package/dist/cjs/modules/gis/enums/trip-privacy.enum.js.map +1 -0
  19. package/dist/cjs/modules/gis/index.js +3 -0
  20. package/dist/cjs/modules/gis/index.js.map +1 -1
  21. package/dist/cjs/modules/gis/interfaces/trip-summary.js +3 -0
  22. package/dist/cjs/modules/gis/interfaces/trip-summary.js.map +1 -0
  23. package/dist/cjs/modules/incident/dtos/incident/incident.dto.js +22 -0
  24. package/dist/cjs/modules/incident/dtos/incident/incident.dto.js.map +1 -1
  25. package/dist/cjs/modules/incident/enums/incident-origin-type.enum.js +17 -0
  26. package/dist/cjs/modules/incident/enums/incident-origin-type.enum.js.map +1 -0
  27. package/dist/cjs/modules/incident/index.js +1 -0
  28. package/dist/cjs/modules/incident/index.js.map +1 -1
  29. package/dist/cjs/modules/organization/index.js +1 -0
  30. package/dist/cjs/modules/organization/index.js.map +1 -1
  31. package/dist/cjs/modules/organization/interfaces/organization-created-event.js +3 -0
  32. package/dist/cjs/modules/organization/interfaces/organization-created-event.js.map +1 -0
  33. package/dist/cjs/modules/permission/data/permissions.data.js +8 -0
  34. package/dist/cjs/modules/permission/data/permissions.data.js.map +1 -1
  35. package/dist/cjs/modules/permission/enums/permission-actions.enum.js +12 -0
  36. package/dist/cjs/modules/permission/enums/permission-actions.enum.js.map +1 -1
  37. package/dist/cjs/modules/permission/enums/permissions-module.enum.js +1 -0
  38. package/dist/cjs/modules/permission/enums/permissions-module.enum.js.map +1 -1
  39. package/dist/cjs/modules/role/constants/safety-roles.js +25 -0
  40. package/dist/cjs/modules/role/constants/safety-roles.js.map +1 -0
  41. package/dist/cjs/modules/role/data/roles.data.js +38 -6
  42. package/dist/cjs/modules/role/data/roles.data.js.map +1 -1
  43. package/dist/cjs/modules/role/index.js +1 -0
  44. package/dist/cjs/modules/role/index.js.map +1 -1
  45. package/dist/cjs/modules/safety/constants/safety-check-limits.const.js +51 -0
  46. package/dist/cjs/modules/safety/constants/safety-check-limits.const.js.map +1 -0
  47. package/dist/cjs/modules/safety/constants/safety-integration.const.js +71 -0
  48. package/dist/cjs/modules/safety/constants/safety-integration.const.js.map +1 -0
  49. package/dist/cjs/modules/safety/constants/safety-taxonomy.const.js +50 -0
  50. package/dist/cjs/modules/safety/constants/safety-taxonomy.const.js.map +1 -0
  51. package/dist/cjs/modules/safety/dtos/safety-admin.dto.js +232 -0
  52. package/dist/cjs/modules/safety/dtos/safety-admin.dto.js.map +1 -0
  53. package/dist/cjs/modules/safety/dtos/safety-check.dto.js +170 -0
  54. package/dist/cjs/modules/safety/dtos/safety-check.dto.js.map +1 -0
  55. package/dist/cjs/modules/safety/dtos/safety-internal.dto.js +162 -0
  56. package/dist/cjs/modules/safety/dtos/safety-internal.dto.js.map +1 -0
  57. package/dist/cjs/modules/safety/enums/safety-check-status.enum.js +45 -0
  58. package/dist/cjs/modules/safety/enums/safety-check-status.enum.js.map +1 -0
  59. package/dist/cjs/modules/safety/enums/safety-enums.js +93 -0
  60. package/dist/cjs/modules/safety/enums/safety-enums.js.map +1 -0
  61. package/dist/cjs/modules/safety/enums/safety-error-code.enum.js +27 -0
  62. package/dist/cjs/modules/safety/enums/safety-error-code.enum.js.map +1 -0
  63. package/dist/cjs/modules/safety/index.js +35 -0
  64. package/dist/cjs/modules/safety/index.js.map +1 -0
  65. package/dist/cjs/modules/safety/interfaces/safety-check-event.js +3 -0
  66. package/dist/cjs/modules/safety/interfaces/safety-check-event.js.map +1 -0
  67. package/dist/cjs/modules/safety/interfaces/safety-check.js +3 -0
  68. package/dist/cjs/modules/safety/interfaces/safety-check.js.map +1 -0
  69. package/dist/cjs/modules/safety/utils/safety-check-state-machine.js +75 -0
  70. package/dist/cjs/modules/safety/utils/safety-check-state-machine.js.map +1 -0
  71. package/dist/cjs/modules/safety/utils/safety-check-timing.util.js +68 -0
  72. package/dist/cjs/modules/safety/utils/safety-check-timing.util.js.map +1 -0
  73. package/dist/cjs/modules/sms/constants/sms-templates.config.js +12 -0
  74. package/dist/cjs/modules/sms/constants/sms-templates.config.js.map +1 -1
  75. package/dist/cjs/modules/sms/enums/sms-template.enum.js +2 -0
  76. package/dist/cjs/modules/sms/enums/sms-template.enum.js.map +1 -1
  77. package/dist/esm/index.js +1 -0
  78. package/dist/esm/index.js.map +1 -1
  79. package/dist/esm/kafka/topics.js +10 -1
  80. package/dist/esm/kafka/topics.js.map +1 -1
  81. package/dist/esm/modules/alert-dispatch/dtos/guardian-audience.dto.js +37 -0
  82. package/dist/esm/modules/alert-dispatch/dtos/guardian-audience.dto.js.map +1 -0
  83. package/dist/esm/modules/alert-dispatch/index.js +4 -0
  84. package/dist/esm/modules/alert-dispatch/index.js.map +1 -1
  85. package/dist/esm/modules/alert-dispatch/interfaces/guardian-audience.js +2 -0
  86. package/dist/esm/modules/alert-dispatch/interfaces/guardian-audience.js.map +1 -0
  87. package/dist/esm/modules/alert-dispatch/utils/guardian-audience.util.js +56 -0
  88. package/dist/esm/modules/alert-dispatch/utils/guardian-audience.util.js.map +1 -0
  89. package/dist/esm/modules/common/constants/service.const.js +1 -0
  90. package/dist/esm/modules/common/constants/service.const.js.map +1 -1
  91. package/dist/esm/modules/gis/dtos/private-trip.dto.js +171 -0
  92. package/dist/esm/modules/gis/dtos/private-trip.dto.js.map +1 -0
  93. package/dist/esm/modules/gis/enums/trip-privacy.enum.js +25 -0
  94. package/dist/esm/modules/gis/enums/trip-privacy.enum.js.map +1 -0
  95. package/dist/esm/modules/gis/index.js +3 -0
  96. package/dist/esm/modules/gis/index.js.map +1 -1
  97. package/dist/esm/modules/gis/interfaces/trip-summary.js +2 -0
  98. package/dist/esm/modules/gis/interfaces/trip-summary.js.map +1 -0
  99. package/dist/esm/modules/incident/dtos/incident/incident.dto.js +23 -1
  100. package/dist/esm/modules/incident/dtos/incident/incident.dto.js.map +1 -1
  101. package/dist/esm/modules/incident/enums/incident-origin-type.enum.js +14 -0
  102. package/dist/esm/modules/incident/enums/incident-origin-type.enum.js.map +1 -0
  103. package/dist/esm/modules/incident/index.js +1 -0
  104. package/dist/esm/modules/incident/index.js.map +1 -1
  105. package/dist/esm/modules/organization/index.js +1 -0
  106. package/dist/esm/modules/organization/index.js.map +1 -1
  107. package/dist/esm/modules/organization/interfaces/organization-created-event.js +2 -0
  108. package/dist/esm/modules/organization/interfaces/organization-created-event.js.map +1 -0
  109. package/dist/esm/modules/permission/data/permissions.data.js +8 -0
  110. package/dist/esm/modules/permission/data/permissions.data.js.map +1 -1
  111. package/dist/esm/modules/permission/enums/permission-actions.enum.js +12 -0
  112. package/dist/esm/modules/permission/enums/permission-actions.enum.js.map +1 -1
  113. package/dist/esm/modules/permission/enums/permissions-module.enum.js +1 -0
  114. package/dist/esm/modules/permission/enums/permissions-module.enum.js.map +1 -1
  115. package/dist/esm/modules/role/constants/safety-roles.js +22 -0
  116. package/dist/esm/modules/role/constants/safety-roles.js.map +1 -0
  117. package/dist/esm/modules/role/data/roles.data.js +38 -6
  118. package/dist/esm/modules/role/data/roles.data.js.map +1 -1
  119. package/dist/esm/modules/role/index.js +1 -0
  120. package/dist/esm/modules/role/index.js.map +1 -1
  121. package/dist/esm/modules/safety/constants/safety-check-limits.const.js +48 -0
  122. package/dist/esm/modules/safety/constants/safety-check-limits.const.js.map +1 -0
  123. package/dist/esm/modules/safety/constants/safety-integration.const.js +67 -0
  124. package/dist/esm/modules/safety/constants/safety-integration.const.js.map +1 -0
  125. package/dist/esm/modules/safety/constants/safety-taxonomy.const.js +45 -0
  126. package/dist/esm/modules/safety/constants/safety-taxonomy.const.js.map +1 -0
  127. package/dist/esm/modules/safety/dtos/safety-admin.dto.js +225 -0
  128. package/dist/esm/modules/safety/dtos/safety-admin.dto.js.map +1 -0
  129. package/dist/esm/modules/safety/dtos/safety-check.dto.js +161 -0
  130. package/dist/esm/modules/safety/dtos/safety-check.dto.js.map +1 -0
  131. package/dist/esm/modules/safety/dtos/safety-internal.dto.js +155 -0
  132. package/dist/esm/modules/safety/dtos/safety-internal.dto.js.map +1 -0
  133. package/dist/esm/modules/safety/enums/safety-check-status.enum.js +42 -0
  134. package/dist/esm/modules/safety/enums/safety-check-status.enum.js.map +1 -0
  135. package/dist/esm/modules/safety/enums/safety-enums.js +90 -0
  136. package/dist/esm/modules/safety/enums/safety-enums.js.map +1 -0
  137. package/dist/esm/modules/safety/enums/safety-error-code.enum.js +24 -0
  138. package/dist/esm/modules/safety/enums/safety-error-code.enum.js.map +1 -0
  139. package/dist/esm/modules/safety/index.js +19 -0
  140. package/dist/esm/modules/safety/index.js.map +1 -0
  141. package/dist/esm/modules/safety/interfaces/safety-check-event.js +2 -0
  142. package/dist/esm/modules/safety/interfaces/safety-check-event.js.map +1 -0
  143. package/dist/esm/modules/safety/interfaces/safety-check.js +2 -0
  144. package/dist/esm/modules/safety/interfaces/safety-check.js.map +1 -0
  145. package/dist/esm/modules/safety/utils/safety-check-state-machine.js +67 -0
  146. package/dist/esm/modules/safety/utils/safety-check-state-machine.js.map +1 -0
  147. package/dist/esm/modules/safety/utils/safety-check-timing.util.js +59 -0
  148. package/dist/esm/modules/safety/utils/safety-check-timing.util.js.map +1 -0
  149. package/dist/esm/modules/sms/constants/sms-templates.config.js +12 -0
  150. package/dist/esm/modules/sms/constants/sms-templates.config.js.map +1 -1
  151. package/dist/esm/modules/sms/enums/sms-template.enum.js +2 -0
  152. package/dist/esm/modules/sms/enums/sms-template.enum.js.map +1 -1
  153. package/dist/types/index.d.ts +1 -0
  154. package/dist/types/kafka/topics.d.ts +4 -0
  155. package/dist/types/modules/alert-dispatch/dtos/guardian-audience.dto.d.ts +6 -0
  156. package/dist/types/modules/alert-dispatch/index.d.ts +3 -0
  157. package/dist/types/modules/alert-dispatch/interfaces/guardian-audience.d.ts +23 -0
  158. package/dist/types/modules/alert-dispatch/utils/guardian-audience.util.d.ts +18 -0
  159. package/dist/types/modules/common/constants/service.const.d.ts +4 -0
  160. package/dist/types/modules/gis/dtos/private-trip.dto.d.ts +42 -0
  161. package/dist/types/modules/gis/enums/trip-privacy.enum.d.ts +22 -0
  162. package/dist/types/modules/gis/index.d.ts +3 -0
  163. package/dist/types/modules/gis/interfaces/client-safe-trip.d.ts +8 -0
  164. package/dist/types/modules/gis/interfaces/trip-summary.d.ts +26 -0
  165. package/dist/types/modules/incident/dtos/incident/incident.dto.d.ts +14 -0
  166. package/dist/types/modules/incident/enums/incident-origin-type.enum.d.ts +12 -0
  167. package/dist/types/modules/incident/index.d.ts +1 -0
  168. package/dist/types/modules/incident/intefaces/incident-category.d.ts +10 -0
  169. package/dist/types/modules/incident/intefaces/incident-type.d.ts +10 -0
  170. package/dist/types/modules/incident/intefaces/incident.d.ts +14 -0
  171. package/dist/types/modules/organization/index.d.ts +1 -0
  172. package/dist/types/modules/organization/interfaces/organization-created-event.d.ts +18 -0
  173. package/dist/types/modules/permission/enums/permission-actions.enum.d.ts +3 -0
  174. package/dist/types/modules/permission/enums/permissions-module.enum.d.ts +2 -1
  175. package/dist/types/modules/role/constants/safety-roles.d.ts +14 -0
  176. package/dist/types/modules/role/index.d.ts +1 -0
  177. package/dist/types/modules/safety/constants/safety-check-limits.const.d.ts +47 -0
  178. package/dist/types/modules/safety/constants/safety-integration.const.d.ts +64 -0
  179. package/dist/types/modules/safety/constants/safety-taxonomy.const.d.ts +31 -0
  180. package/dist/types/modules/safety/dtos/safety-admin.dto.d.ts +39 -0
  181. package/dist/types/modules/safety/dtos/safety-check.dto.d.ts +38 -0
  182. package/dist/types/modules/safety/dtos/safety-internal.dto.d.ts +51 -0
  183. package/dist/types/modules/safety/enums/safety-check-status.enum.d.ts +40 -0
  184. package/dist/types/modules/safety/enums/safety-enums.d.ts +81 -0
  185. package/dist/types/modules/safety/enums/safety-error-code.enum.d.ts +22 -0
  186. package/dist/types/modules/safety/index.d.ts +13 -0
  187. package/dist/types/modules/safety/interfaces/safety-check-event.d.ts +36 -0
  188. package/dist/types/modules/safety/interfaces/safety-check.d.ts +180 -0
  189. package/dist/types/modules/safety/utils/safety-check-state-machine.d.ts +30 -0
  190. package/dist/types/modules/safety/utils/safety-check-timing.util.d.ts +37 -0
  191. package/dist/types/modules/sms/enums/sms-template.enum.d.ts +2 -0
  192. package/package.json +1 -1
@@ -0,0 +1,59 @@
1
+ import { SAFETY_CHECK_LIMITS } from '../constants/safety-check-limits.const';
2
+ const MINUTE_MS = 60000;
3
+ /** Validates a requested duration against the platform limits. */
4
+ export function validateSafetyCheckDuration(minutes) {
5
+ if (typeof minutes !== 'number' || !Number.isInteger(minutes))
6
+ return { valid: false, reason: 'NOT_AN_INTEGER' };
7
+ if (minutes < SAFETY_CHECK_LIMITS.minDurationMinutes)
8
+ return { valid: false, reason: 'TOO_SHORT' };
9
+ if (minutes > SAFETY_CHECK_LIMITS.maxDurationMinutes)
10
+ return { valid: false, reason: 'TOO_LONG' };
11
+ return { valid: true };
12
+ }
13
+ /** Whether a prompt countdown (seconds) is within the configurable range. */
14
+ export function isValidPromptCountdownSeconds(seconds) {
15
+ return (typeof seconds === 'number' &&
16
+ Number.isInteger(seconds) &&
17
+ seconds >= SAFETY_CHECK_LIMITS.minPromptCountdownSeconds &&
18
+ seconds <= SAFETY_CHECK_LIMITS.maxPromptCountdownSeconds);
19
+ }
20
+ /** The latest moment a check started at `startedAt` may be scheduled to check in. */
21
+ export function latestAllowedCheckInAt(startedAt) {
22
+ return new Date(startedAt.getTime() + SAFETY_CHECK_LIMITS.maxDurationMinutes * MINUTE_MS);
23
+ }
24
+ /**
25
+ * Plans an extension. While the check-in time is still ahead the extension is
26
+ * added to it; once it has passed (the user is being prompted) it counts from
27
+ * now. Either way the result may not end more than maxDurationMinutes after the
28
+ * check started - an extension never lets a check outlive the 24 hour cap.
29
+ */
30
+ export function planSafetyCheckExtension(input) {
31
+ const cap = latestAllowedCheckInAt(input.startedAt).getTime();
32
+ const base = Math.max(input.scheduledCheckInAt.getTime(), input.now.getTime());
33
+ const maxAdditionalMinutes = Math.max(0, Math.floor((cap - base) / MINUTE_MS));
34
+ if (!Number.isInteger(input.additionalMinutes) || input.additionalMinutes < 1) {
35
+ return { allowed: false, maxAdditionalMinutes };
36
+ }
37
+ const next = base + input.additionalMinutes * MINUTE_MS;
38
+ if (next > cap)
39
+ return { allowed: false, maxAdditionalMinutes };
40
+ return {
41
+ allowed: true,
42
+ scheduledCheckInAt: new Date(next),
43
+ totalDurationMinutes: Math.round((next - input.startedAt.getTime()) / MINUTE_MS),
44
+ maxAdditionalMinutes,
45
+ };
46
+ }
47
+ /** When the prompt shown at `promptStartedAt` runs out (what the user sees). */
48
+ export function promptDeadlineFrom(promptStartedAt, promptCountdownSeconds) {
49
+ return new Date(promptStartedAt.getTime() + promptCountdownSeconds * 1000);
50
+ }
51
+ /** When the server actually raises the SOS: the visible deadline plus the grace. */
52
+ export function sosDueAt(promptDeadlineAt) {
53
+ return new Date(promptDeadlineAt.getTime() + SAFETY_CHECK_LIMITS.checkInGraceSeconds * 1000);
54
+ }
55
+ /** Whether an SOS that fell due at `dueAt` is too stale to raise at `now`. */
56
+ export function isSosTooStale(dueAt, now) {
57
+ return now.getTime() - dueAt.getTime() > SAFETY_CHECK_LIMITS.staleSosWindowMinutes * MINUTE_MS;
58
+ }
59
+ //# sourceMappingURL=safety-check-timing.util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"safety-check-timing.util.js","sourceRoot":"","sources":["../../../../../src/modules/safety/utils/safety-check-timing.util.ts"],"names":[],"mappings":"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"}
@@ -43,6 +43,18 @@ export const SMS_TEMPLATES = {
43
43
  variables: ['REPORTER_FIRSTNAME', 'GUARDIAN_FIRSTNAME', 'APP_NAME', 'LOCATION_LINK'],
44
44
  description: 'Template for incident guardian notifications'
45
45
  },
46
+ [SmsTemplateType.SAFETY_CHECK_GUARDIAN_STARTED]: {
47
+ name: 'Safety Check Started (Guardian)',
48
+ content: '{{GUARDIAN_FIRSTNAME}}, {{USER_FIRSTNAME}} has started a Safety Check on {{APP_NAME}} ({{REASON}}) and expects to check in by {{CHECK_IN_TIME}}. If they do not, you will be alerted. Nothing to do for now.',
49
+ variables: ['GUARDIAN_FIRSTNAME', 'USER_FIRSTNAME', 'APP_NAME', 'REASON', 'CHECK_IN_TIME'],
50
+ description: 'Tells an external guardian that someone who chose them started a Safety Check'
51
+ },
52
+ [SmsTemplateType.SAFETY_CHECK_GUARDIAN_ENDED]: {
53
+ name: 'Safety Check Ended (Guardian)',
54
+ content: '{{GUARDIAN_FIRSTNAME}}, {{USER_FIRSTNAME}} {{OUTCOME}} on {{APP_NAME}}. Nothing to do.',
55
+ variables: ['GUARDIAN_FIRSTNAME', 'USER_FIRSTNAME', 'OUTCOME', 'APP_NAME'],
56
+ description: 'Tells an external guardian that a Safety Check ended without an SOS'
57
+ },
46
58
  [SmsTemplateType.APPOINTMENT_REMINDER]: {
47
59
  name: 'Appointment Reminder',
48
60
  content: 'Reminder: You have an appointment on {{DATE}} at {{TIME}} for {{PURPOSE}}. Location: {{LOCATION}}. Contact us if you need to reschedule.',
@@ -1 +1 @@
1
- {"version":3,"file":"sms-templates.config.js","sourceRoot":"","sources":["../../../../../src/modules/sms/constants/sms-templates.config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC5C,SAAS,EAAE;QACP,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE;YAChC,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,qIAAqI;YAC9I,SAAS,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC;YACpC,WAAW,EAAE,6CAA6C;SAC7D;QACD,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE;YAC9B,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,oKAAoK;YAC7K,SAAS,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC;YACpC,WAAW,EAAE,gDAAgD;SAChE;QACD,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE;YACvB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,6HAA6H;YACtI,SAAS,EAAE,CAAC,mBAAmB,EAAE,MAAM,CAAC;YACxC,WAAW,EAAE,+BAA+B;SAC/C;QACD,CAAC,eAAe,CAAC,kBAAkB,CAAC,EAAE;YAClC,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,2IAA2I;YACpJ,SAAS,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC;YAC5C,WAAW,EAAE,uCAAuC;SACvD;QACD,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE;YAC9B,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,iHAAiH;YAC1H,SAAS,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;YACzC,WAAW,EAAE,gDAAgD;SAChE;QACD,CAAC,eAAe,CAAC,qBAAqB,CAAC,EAAE;YACrC,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,yHAAyH;YAClI,SAAS,EAAE,CAAC,gBAAgB,EAAE,aAAa,CAAC;YAC5C,WAAW,EAAE,qCAAqC;SACrD;QACD,CAAC,eAAe,CAAC,8BAA8B,CAAC,EAAE;YAC9C,IAAI,EAAE,gCAAgC;YACtC,OAAO,EAAE,oPAAoP;YAC7P,SAAS,EAAE,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;YACpF,WAAW,EAAE,8CAA8C;SAC9D;QACD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE;YACpC,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,0IAA0I;YACnJ,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC;YAClD,WAAW,EAAE,oCAAoC;SACpD;QACD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE;YACpC,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,CAAC,SAAS,CAAC;YACtB,WAAW,EAAE,uCAAuC;SACvD;KACJ;CACJ,CAAC"}
1
+ {"version":3,"file":"sms-templates.config.js","sourceRoot":"","sources":["../../../../../src/modules/sms/constants/sms-templates.config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAE7D,MAAM,CAAC,MAAM,aAAa,GAAsB;IAC5C,SAAS,EAAE;QACP,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE;YAChC,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,qIAAqI;YAC9I,SAAS,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC;YACpC,WAAW,EAAE,6CAA6C;SAC7D;QACD,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE;YAC9B,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,oKAAoK;YAC7K,SAAS,EAAE,CAAC,KAAK,EAAE,gBAAgB,CAAC;YACpC,WAAW,EAAE,gDAAgD;SAChE;QACD,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE;YACvB,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,6HAA6H;YACtI,SAAS,EAAE,CAAC,mBAAmB,EAAE,MAAM,CAAC;YACxC,WAAW,EAAE,+BAA+B;SAC/C;QACD,CAAC,eAAe,CAAC,kBAAkB,CAAC,EAAE;YAClC,IAAI,EAAE,oBAAoB;YAC1B,OAAO,EAAE,2IAA2I;YACpJ,SAAS,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC;YAC5C,WAAW,EAAE,uCAAuC;SACvD;QACD,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE;YAC9B,IAAI,EAAE,gBAAgB;YACtB,OAAO,EAAE,iHAAiH;YAC1H,SAAS,EAAE,CAAC,eAAe,EAAE,WAAW,CAAC;YACzC,WAAW,EAAE,gDAAgD;SAChE;QACD,CAAC,eAAe,CAAC,qBAAqB,CAAC,EAAE;YACrC,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,yHAAyH;YAClI,SAAS,EAAE,CAAC,gBAAgB,EAAE,aAAa,CAAC;YAC5C,WAAW,EAAE,qCAAqC;SACrD;QACD,CAAC,eAAe,CAAC,8BAA8B,CAAC,EAAE;YAC9C,IAAI,EAAE,gCAAgC;YACtC,OAAO,EAAE,oPAAoP;YAC7P,SAAS,EAAE,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;YACpF,WAAW,EAAE,8CAA8C;SAC9D;QACD,CAAC,eAAe,CAAC,6BAA6B,CAAC,EAAE;YAC7C,IAAI,EAAE,iCAAiC;YACvC,OAAO,EAAE,8MAA8M;YACvN,SAAS,EAAE,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC;YAC1F,WAAW,EAAE,+EAA+E;SAC/F;QACD,CAAC,eAAe,CAAC,2BAA2B,CAAC,EAAE;YAC3C,IAAI,EAAE,+BAA+B;YACrC,OAAO,EAAE,wFAAwF;YACjG,SAAS,EAAE,CAAC,oBAAoB,EAAE,gBAAgB,EAAE,SAAS,EAAE,UAAU,CAAC;YAC1E,WAAW,EAAE,qEAAqE;SACrF;QACD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE;YACpC,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,0IAA0I;YACnJ,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC;YAClD,WAAW,EAAE,oCAAoC;SACpD;QACD,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE;YACpC,IAAI,EAAE,sBAAsB;YAC5B,OAAO,EAAE,aAAa;YACtB,SAAS,EAAE,CAAC,SAAS,CAAC;YACtB,WAAW,EAAE,uCAAuC;SACvD;KACJ;CACJ,CAAC"}
@@ -7,6 +7,8 @@ export var SmsTemplateType;
7
7
  SmsTemplateType["SECURITY_ALERT"] = "security_alert";
8
8
  SmsTemplateType["INCIDENT_NOTIFICATION"] = "incident_notification";
9
9
  SmsTemplateType["INCIDENT_GUARDIAN_NOTIFICATION"] = "incident_guardian_notification";
10
+ SmsTemplateType["SAFETY_CHECK_GUARDIAN_STARTED"] = "safety_check_guardian_started";
11
+ SmsTemplateType["SAFETY_CHECK_GUARDIAN_ENDED"] = "safety_check_guardian_ended";
10
12
  SmsTemplateType["APPOINTMENT_REMINDER"] = "appointment_reminder";
11
13
  SmsTemplateType["GENERAL_NOTIFICATION"] = "general_notification";
12
14
  })(SmsTemplateType || (SmsTemplateType = {}));
@@ -1 +1 @@
1
- {"version":3,"file":"sms-template.enum.js","sourceRoot":"","sources":["../../../../../src/modules/sms/enums/sms-template.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,eAUX;AAVD,WAAY,eAAe;IACvB,wDAAqC,CAAA;IACrC,oDAAiC,CAAA;IACjC,sCAAmB,CAAA;IACnB,4DAAyC,CAAA;IACzC,oDAAiC,CAAA;IACjC,kEAA+C,CAAA;IAC/C,oFAAiE,CAAA;IACjE,gEAA6C,CAAA;IAC7C,gEAA6C,CAAA;AACjD,CAAC,EAVW,eAAe,KAAf,eAAe,QAU1B"}
1
+ {"version":3,"file":"sms-template.enum.js","sourceRoot":"","sources":["../../../../../src/modules/sms/enums/sms-template.enum.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,eAYX;AAZD,WAAY,eAAe;IACvB,wDAAqC,CAAA;IACrC,oDAAiC,CAAA;IACjC,sCAAmB,CAAA;IACnB,4DAAyC,CAAA;IACzC,oDAAiC,CAAA;IACjC,kEAA+C,CAAA;IAC/C,oFAAiE,CAAA;IACjE,kFAA+D,CAAA;IAC/D,8EAA2D,CAAA;IAC3D,gEAA6C,CAAA;IAC7C,gEAA6C,CAAA;AACjD,CAAC,EAZW,eAAe,KAAf,eAAe,QAY1B"}
@@ -25,6 +25,7 @@ export * from './modules/system-user/index';
25
25
  export * from './modules/partner/index';
26
26
  export * from './modules/support/index';
27
27
  export * from './modules/alert-intake/index';
28
+ export * from './modules/safety/index';
28
29
  export * from './interfaces/server-message';
29
30
  export * from './interfaces/i-request-with-user';
30
31
  export * from './interfaces/validated-user';
@@ -76,4 +76,8 @@ export declare const KAFKA_TOPICS: {
76
76
  SUPPORT_FEEDBACK_RATING_SUBMITTED: string;
77
77
  SUPPORT_PROVIDER_SYNC_FAILED: string;
78
78
  SUPPORT_PROVIDER_SYNC_RECOVERED: string;
79
+ SAFETY_CHECK_STARTED: string;
80
+ SAFETY_CHECK_PROMPTING: string;
81
+ SAFETY_CHECK_ENDED: string;
82
+ SAFETY_CHECK_SOS_TRIGGERED: string;
79
83
  };
@@ -0,0 +1,6 @@
1
+ import { GuardianAudience } from '../interfaces/guardian-audience';
2
+ /** Validated GuardianAudience - see the interface for what absent vs present means. */
3
+ export declare class GuardianAudienceDto implements GuardianAudience {
4
+ systemGuardianUserIds: number[];
5
+ externalGuardianPhoneNumbers: string[];
6
+ }
@@ -1,3 +1,6 @@
1
1
  export * from './enums/incident-dispatch-scope.enum';
2
2
  export * from './interfaces/alert-dispatch';
3
+ export * from './interfaces/guardian-audience';
4
+ export * from './dtos/guardian-audience.dto';
3
5
  export * from './utils/alert-dispatch.util';
6
+ export * from './utils/guardian-audience.util';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Which of a reporter's guardians an alert is for.
3
+ *
4
+ * Absent (null/undefined) means EVERY guardian - the behaviour every incident had
5
+ * before audiences existed, and still the behaviour of a plain SOS. Present means
6
+ * exactly these guardians and nobody else: a Safety Check's SOS goes only to the
7
+ * guardians the user ticked when they started it.
8
+ *
9
+ * Guardians are identified the way clarion-authentication identifies them:
10
+ * app-user guardians by their user id, external contacts by their E.164 phone
11
+ * number (they have no other id).
12
+ */
13
+ export interface GuardianAudience {
14
+ systemGuardianUserIds: number[];
15
+ externalGuardianPhoneNumbers: string[];
16
+ }
17
+ /** The two guardian shapes clarion-authentication's alert-contacts endpoint returns. */
18
+ export interface GuardianAudienceCandidate {
19
+ /** Set for an app-user guardian. */
20
+ userId?: number | null;
21
+ /** Also the identity of an external guardian. */
22
+ phoneNumber?: string | null;
23
+ }
@@ -0,0 +1,18 @@
1
+ import { GuardianAudience, GuardianAudienceCandidate } from '../interfaces/guardian-audience';
2
+ /** Canonical form used to compare guardian phone numbers. */
3
+ export declare function canonicalGuardianPhone(value: string | null | undefined): string | null;
4
+ /** An audience with duplicates removed and phone numbers canonicalised. */
5
+ export declare function normalizeGuardianAudience(audience: GuardianAudience): GuardianAudience;
6
+ /** True when an audience names nobody at all. */
7
+ export declare function isEmptyGuardianAudience(audience: GuardianAudience | null | undefined): boolean;
8
+ /**
9
+ * Whether one guardian is in the audience. A missing audience includes everyone.
10
+ *
11
+ * An app-user guardian matches on user id first. A guardian that arrives without a
12
+ * user id (an external contact) matches on phone number - and so does an app user
13
+ * the audience listed by phone, because a contact who installed the app after
14
+ * being added keeps the number they were chosen by.
15
+ */
16
+ export declare function isInGuardianAudience(candidate: GuardianAudienceCandidate, audience: GuardianAudience | null | undefined): boolean;
17
+ /** Keeps only the guardians in the audience. A missing audience keeps everyone. */
18
+ export declare function filterByGuardianAudience<T>(guardians: readonly T[], audience: GuardianAudience | null | undefined, identify: (guardian: T) => GuardianAudienceCandidate): T[];
@@ -67,4 +67,8 @@ export declare const SERVICE_CONSTS: {
67
67
  name: string;
68
68
  port: number;
69
69
  };
70
+ SAFETY_SERVICE: {
71
+ name: string;
72
+ port: number;
73
+ };
70
74
  };
@@ -0,0 +1,42 @@
1
+ import { TripPurpose } from '../enums/trip-privacy.enum';
2
+ /** One recorded fix. Same shape as the SOS track points clarion-gis already stores. */
3
+ export declare class TripTrackPointDto {
4
+ lat: number;
5
+ lng: number;
6
+ accuracy?: number;
7
+ timestamp: string;
8
+ }
9
+ export declare class TripStartLocationDto {
10
+ lat: number;
11
+ lng: number;
12
+ }
13
+ /**
14
+ * clarion-safety -> clarion-gis (internal): open a PRIVATE trip for a safety
15
+ * record. Idempotent on (purpose, sourceReferenceId).
16
+ */
17
+ export declare class CreatePrivateTripDto {
18
+ purpose: TripPurpose;
19
+ sourceReferenceId: string;
20
+ userId: number;
21
+ organizationId: number;
22
+ controlCentreId?: number;
23
+ startLocation?: TripStartLocationDto;
24
+ }
25
+ /** Append fixes to a trip by id. `userId` must be the trip's owner. */
26
+ export declare class AddTripTrackPointsDto {
27
+ userId: number;
28
+ points: TripTrackPointDto[];
29
+ }
30
+ /**
31
+ * Turn a PRIVATE trip into the trip of an SOS incident. Idempotent for the same
32
+ * incident; refused (409) for a different one.
33
+ */
34
+ export declare class ShareTripDto {
35
+ incidentId: number;
36
+ targetUserIds?: number[];
37
+ }
38
+ /** End a PRIVATE trip without telling anyone (no realtime, no Kafka). */
39
+ export declare class StopPrivateTripDto {
40
+ endLat?: number;
41
+ endLng?: number;
42
+ }
@@ -0,0 +1,22 @@
1
+ /** Why a trip is being recorded. */
2
+ export declare enum TripPurpose {
3
+ /** The trip of an SOS incident - every trip before safety features existed. */
4
+ SOS = "SOS",
5
+ /** Recorded during a Safety Check. */
6
+ SAFETY_CHECK = "SAFETY_CHECK"
7
+ }
8
+ /**
9
+ * Who a trip is visible to.
10
+ *
11
+ * PRIVATE: only its owner. clarion-gis publishes nothing about it - no realtime
12
+ * event, no Kafka event - and it has no incident, so no incident-scoped route can
13
+ * reach it. A Safety Check trip is PRIVATE while the check runs.
14
+ *
15
+ * SHARED: an incident trip, visible under the existing SOS rules. A PRIVATE trip
16
+ * becomes SHARED exactly once, when an SOS is raised for it; its whole recorded
17
+ * history is shared at that moment.
18
+ */
19
+ export declare enum TripVisibility {
20
+ PRIVATE = "PRIVATE",
21
+ SHARED = "SHARED"
22
+ }
@@ -13,6 +13,7 @@ export * from './dtos/find-zones-near-point.dto';
13
13
  export * from './dtos/geo-json-polygon.dto';
14
14
  export * from './dtos/point-containment-result.dto';
15
15
  export * from './dtos/point-location.dto';
16
+ export * from './dtos/private-trip.dto';
16
17
  export * from './dtos/post-gis-geometry.dto';
17
18
  export * from './dtos/route-incident.dto';
18
19
  export * from './dtos/routing-coverage-result.dto';
@@ -25,6 +26,7 @@ export * from './dtos/zone-statistics-result.dto';
25
26
  export * from './dtos/zone-with-distance-result.dto';
26
27
  export * from './enums/incident-routing-result-match-type.enum';
27
28
  export * from './enums/trip-actions.enum';
29
+ export * from './enums/trip-privacy.enum';
28
30
  export * from './enums/zone.enums';
29
31
  export * from './interfaces/client-safe-trip';
30
32
  export * from './interfaces/control-centre-routing-result';
@@ -32,6 +34,7 @@ export * from './interfaces/incident-routing-result';
32
34
  export * from './interfaces/point-containment';
33
35
  export * from './interfaces/point-location';
34
36
  export * from './interfaces/polygon-validation-result';
37
+ export * from './interfaces/trip-summary';
35
38
  export * from './interfaces/zone';
36
39
  export * from './interfaces/zone-for-point';
37
40
  export * from './interfaces/zone-match-result';
@@ -1,3 +1,4 @@
1
+ import { TripPurpose, TripVisibility } from '../enums/trip-privacy.enum';
1
2
  export interface ClientSafeTrip {
2
3
  id: string;
3
4
  incidentId: number;
@@ -22,4 +23,11 @@ export interface ClientSafeTrip {
22
23
  startedAt: string;
23
24
  endedAt: string | null;
24
25
  distanceMeters: number | null;
26
+ /**
27
+ * Absent on events from a clarion-gis that predates private trips (all SOS).
28
+ * clarion-socket refuses to deliver any trip event marked PRIVATE - a private
29
+ * trip must never reach a room, whatever published it.
30
+ */
31
+ purpose?: TripPurpose;
32
+ visibility?: TripVisibility;
25
33
  }
@@ -0,0 +1,26 @@
1
+ import { TripPurpose, TripVisibility } from '../enums/trip-privacy.enum';
2
+ /**
3
+ * A trip without its path - what clarion-safety needs to run a check and what an
4
+ * admin may see of it. `lastPoint` is for clarion-safety alone (the SOS location);
5
+ * clarion-safety never forwards it to a client before the trip is SHARED.
6
+ */
7
+ export interface TripSummary {
8
+ id: string;
9
+ purpose: TripPurpose;
10
+ visibility: TripVisibility;
11
+ status: string;
12
+ incidentId: number | null;
13
+ userId: number;
14
+ organizationId: number;
15
+ startedAt: string;
16
+ endedAt: string | null;
17
+ sharedAt: string | null;
18
+ distanceMeters: number | null;
19
+ trackPointCount: number;
20
+ lastPoint: {
21
+ lat: number;
22
+ lng: number;
23
+ accuracy?: number;
24
+ timestamp: string;
25
+ } | null;
26
+ }
@@ -7,6 +7,8 @@ import { IncidentResponseUnitAssignmentDto } from "../response-unit-assignment/u
7
7
  import { IncidentReporterDto } from "../reporter/incident-reporter.dto";
8
8
  import { IncidentStatusDetailsDto } from "./incident-status-details.dto";
9
9
  import { IncidentEntitlementTier } from "../../../entitlement/enums/incident-entitlement-tier.enum";
10
+ import { IncidentOriginType } from "../../enums/incident-origin-type.enum";
11
+ import { GuardianAudienceDto } from "../../../alert-dispatch/dtos/guardian-audience.dto";
10
12
  declare const IncidentDto_base: import("@nestjs/common").Type<Omit<CreateIncidentDto, "reporter" | "statusDetails">>;
11
13
  export declare class IncidentDto extends IncidentDto_base {
12
14
  id: number;
@@ -26,5 +28,17 @@ export declare class IncidentDto extends IncidentDto_base {
26
28
  * alert from an entitled one without calling back into billing.
27
29
  */
28
30
  entitlementTier?: IncidentEntitlementTier;
31
+ /**
32
+ * Set when a safety feature raised the incident. Read-only: CreateIncidentDto
33
+ * has no such field, so nobody can claim an origin through POST /incidents.
34
+ */
35
+ originType?: IncidentOriginType | null;
36
+ originReferenceId?: string | null;
37
+ /**
38
+ * Which guardians the alert is for; absent means all of them. Whitelisted here
39
+ * because clarion-notification validates this DTO with `whitelist: true` - a
40
+ * field missing from it would be stripped and every guardian alerted.
41
+ */
42
+ guardianAudience?: GuardianAudienceDto | null;
29
43
  }
30
44
  export {};
@@ -0,0 +1,12 @@
1
+ /**
2
+ * What raised an incident when it was not a person filling in a form. Stored on
3
+ * the incident with `originReferenceId` (the raising record's id); the pair is
4
+ * UNIQUE, which is what makes an automatic SOS impossible to raise twice.
5
+ *
6
+ * Absent for every incident a person raised - the SOS sheet, the admin, the
7
+ * public channels.
8
+ */
9
+ export declare enum IncidentOriginType {
10
+ /** A Safety Check the user missed or asked for help from. */
11
+ SAFETY_CHECK = "SAFETY_CHECK"
12
+ }
@@ -37,6 +37,7 @@ export * from './enums/incident-status.enum';
37
37
  export * from './enums/incident-actions.enum';
38
38
  export * from './enums/incident-workflow-queue-name.enum';
39
39
  export * from './enums/incident-emergency-type.enum';
40
+ export * from './enums/incident-origin-type.enum';
40
41
  export * from './intefaces/incident';
41
42
  export * from './intefaces/incident-action';
42
43
  export * from './intefaces/incident-attachment';
@@ -4,5 +4,15 @@ export interface IncidentCategory {
4
4
  name: string;
5
5
  description?: string;
6
6
  organizationId: number;
7
+ /**
8
+ * Stable code of a platform-managed row (e.g. SAFETY_CHECK_SOS); null for
9
+ * everything an organization created itself.
10
+ */
11
+ code?: string | null;
12
+ /**
13
+ * Platform-managed: provisioned for every organization, hidden from the SOS
14
+ * sheet and from package configuration, and not editable or deletable.
15
+ */
16
+ isSystem?: boolean;
7
17
  types?: IncidentType[];
8
18
  }
@@ -5,5 +5,15 @@ export interface IncidentType {
5
5
  description?: string;
6
6
  categoryId?: number;
7
7
  organizationId: number;
8
+ /**
9
+ * Stable code of a platform-managed row (e.g. SAFETY_CHECK_SOS); null for
10
+ * everything an organization created itself.
11
+ */
12
+ code?: string | null;
13
+ /**
14
+ * Platform-managed: provisioned for every organization, hidden from the SOS
15
+ * sheet and from package configuration, and not editable or deletable.
16
+ */
17
+ isSystem?: boolean;
8
18
  category?: IncidentCategory;
9
19
  }
@@ -5,6 +5,8 @@ import { IncidentClass } from "../enums/incident-class.enum";
5
5
  import { IncidentPriority } from "../enums/incident-priority.enum";
6
6
  import { IncidentStatus } from "../enums/incident-status.enum";
7
7
  import { IncidentWorkflowTaskQueueName } from "../enums/incident-workflow-queue-name.enum";
8
+ import { IncidentOriginType } from "../enums/incident-origin-type.enum";
9
+ import { GuardianAudience } from "../../alert-dispatch/interfaces/guardian-audience";
8
10
  import { IncidentAction } from "./incident-action";
9
11
  import { IncidentAssignment } from "./incident-assignment";
10
12
  import { IncidentCategory } from "./incident-category";
@@ -88,6 +90,18 @@ export interface Incident {
88
90
  * billing withheld is not an alert somebody chose to withhold.
89
91
  */
90
92
  notifyServiceProviderRequested?: boolean;
93
+ /**
94
+ * Set when a safety feature raised the incident (see IncidentOriginType).
95
+ * Absent for everything a person raised.
96
+ */
97
+ originType?: IncidentOriginType | null;
98
+ originReferenceId?: string | null;
99
+ /**
100
+ * Which guardians the alert is for. Absent (the norm) means all of the
101
+ * reporter's guardians; a Safety Check SOS carries exactly the ones the user
102
+ * selected. Honoured by clarion-notification and by the incident chat.
103
+ */
104
+ guardianAudience?: GuardianAudience | null;
91
105
  createdAt?: string;
92
106
  updatedAt?: string;
93
107
  category?: IncidentCategory;
@@ -3,5 +3,6 @@ export * from './dtos/update-organization.dto';
3
3
  export * from './dtos/organization-sla.dto';
4
4
  export * from './interfaces/organization';
5
5
  export * from './interfaces/organization-sla';
6
+ export * from './interfaces/organization-created-event';
6
7
  export * from './enums/org-status.enum';
7
8
  export * from './enums/org-type.enum';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Payload of KAFKA_TOPICS.ORG_CREATED, published by clarion-organization after
3
+ * the organization (and its HQ control centre) has been committed. Consumers
4
+ * provision their per-organization defaults from it - clarion-incident creates
5
+ * the Safety Alerts category - and must be idempotent: the event is delivered at
6
+ * least once, and every consumer also reconciles on its own schedule, so a lost
7
+ * event delays provisioning rather than skipping it.
8
+ */
9
+ export interface OrganizationCreatedEvent {
10
+ eventId: string;
11
+ occurredAt: string;
12
+ organizationId: number;
13
+ name: string;
14
+ countryCode: string | null;
15
+ incidentClass: string | null;
16
+ appId: string | null;
17
+ hqControlCentreId: number | null;
18
+ }
@@ -191,6 +191,9 @@ export declare enum PermissionActions {
191
191
  REVIEW_ALERT_INTAKE_SCREENED_MESSAGE = "review:alert-intake-screened-message",
192
192
  READ_ALERT_INTAKE_ANALYTICS = "read:alert-intake-analytics",
193
193
  MANAGE_ALERT_INTAKE_PLATFORM = "manage:alert-intake-platform",
194
+ USE_SAFETY_CHECK = "use:safety-check",
195
+ READ_SAFETY_CHECK = "read:safety-check",
196
+ MANAGE_SAFETY_CHECK_REASON = "manage:safety-check-reason",
194
197
  /**
195
198
  * @deprecated Split into the connection / message / screened-message /
196
199
  * analytics actions above, which the gateway now requires instead. Still
@@ -12,5 +12,6 @@ export declare enum PermissionsModule {
12
12
  NEWSFEED = "Newsfeed",
13
13
  SUPPORT = "Support",
14
14
  NOTIFICATION = "Notification",
15
- ALERT_INTAKE = "Alert Intake"
15
+ ALERT_INTAKE = "Alert Intake",
16
+ SAFETY = "Safety"
16
17
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The organization roles that curate the Safety Check reasons their app offers.
3
+ * Each holds manage:safety-check-reason (roles.spec.ts asserts it). Platform-wide
4
+ * reasons are Super-Admin's alone.
5
+ *
6
+ * For the places that decide by role NAME: clarion-safety's own scoping and the
7
+ * admin deciding whether to offer an edit at all.
8
+ */
9
+ export declare const SAFETY_MANAGER_ROLES: string[];
10
+ /**
11
+ * The staff roles that may read Safety Checks: the managers across the whole
12
+ * organization, and a control-centre admin within their control centre.
13
+ */
14
+ export declare const SAFETY_VIEWER_ROLES: string[];
@@ -6,3 +6,4 @@ export * from './interfaces/role';
6
6
  export * from './constants/roles-by-scope';
7
7
  export * from './constants/billing-roles';
8
8
  export * from './constants/newsfeed-roles';
9
+ export * from './constants/safety-roles';
@@ -0,0 +1,47 @@
1
+ /**
2
+ * The Safety Check limits. The mobile app, the gateway-facing DTOs and the
3
+ * clarion-safety domain all read THESE numbers, so client-side and server-side
4
+ * validation cannot drift apart. The app additionally receives them from
5
+ * GET /safety/checks/start-options rather than hard-coding its own copy.
6
+ */
7
+ export declare const SAFETY_CHECK_LIMITS: {
8
+ /** Shortest check the platform accepts. */
9
+ readonly minDurationMinutes: 1;
10
+ /** Longest check - including every extension - measured from startedAt. */
11
+ readonly maxDurationMinutes: number;
12
+ readonly defaultDurationMinutes: 15;
13
+ /** The quick picks offered on the setup screen ("Other" is a custom value). */
14
+ readonly presetDurationsMinutes: readonly number[];
15
+ /** How long the user has to confirm once prompted. */
16
+ readonly minPromptCountdownSeconds: 15;
17
+ readonly maxPromptCountdownSeconds: number;
18
+ readonly defaultPromptCountdownSeconds: 60;
19
+ /**
20
+ * Server-side grace after the visible countdown reaches zero before the SOS is
21
+ * raised. Covers an "I'm OK" that was sent at the last second and is still in
22
+ * flight. The app never shows it - the countdown it shows ends at
23
+ * promptDeadlineAt.
24
+ */
25
+ readonly checkInGraceSeconds: 10;
26
+ /**
27
+ * A check whose check-in window closed longer ago than this - only possible
28
+ * after a platform outage - is EXPIRED instead of raising an SOS hours late.
29
+ */
30
+ readonly staleSosWindowMinutes: number;
31
+ /** Free-text reason for "Write my own". */
32
+ readonly customReasonMaxLength: 120;
33
+ /** One track-point upload. */
34
+ readonly maxTrackPointsPerBatch: 200;
35
+ };
36
+ /** Where the setup screen starts. */
37
+ export declare const SAFETY_CHECK_DEFAULTS: {
38
+ readonly durationMinutes: 15;
39
+ readonly promptCountdownSeconds: 60;
40
+ /** Every eligible guardian starts selected. */
41
+ readonly allGuardiansSelected: true;
42
+ /** Premium/Trial only - Free users are never offered the option. */
43
+ readonly notifyServiceProvider: true;
44
+ readonly notifyGuardiansOnStartEnd: true;
45
+ readonly vibrate: true;
46
+ readonly alarmSound: true;
47
+ };
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Cross-service contracts for the Safety domain. Each value is read by more than
3
+ * one repository - change both sides together.
4
+ */
5
+ /**
6
+ * Header carrying the shared internal service token on the calls that can raise
7
+ * or steer an SOS: workflow-manager -> clarion-safety (advance), clarion-safety
8
+ * -> workflow-manager (start/signal) and clarion-safety -> clarion-incident
9
+ * (create the Safety SOS incident). Same header workflow-manager already
10
+ * requires on its API.
11
+ */
12
+ export declare const SAFETY_INTERNAL_TOKEN_HEADER = "x-internal-service-token";
13
+ /**
14
+ * Env vars the token is read from, in order. `SAFETY_INTERNAL_API_TOKEN` may hold
15
+ * a comma-separated list (rotation); when it is unset every party falls back to
16
+ * `WORKFLOW_MANAGER_API_TOKEN`, which every pod already receives from
17
+ * runtime-secrets. Senders use the FIRST value; receivers accept ANY.
18
+ */
19
+ export declare const SAFETY_INTERNAL_TOKEN_ENV_KEYS: readonly ["SAFETY_INTERNAL_API_TOKEN", "WORKFLOW_MANAGER_API_TOKEN"];
20
+ /** Temporal: the durable Safety Check timer. */
21
+ export declare const SAFETY_CHECK_WORKFLOW: {
22
+ /** Registered workflow function name in clarion-workflow-manager. */
23
+ readonly workflowType: "safetyCheckWorkflow";
24
+ /** Default task queue; overridable with TEMPORAL_SAFETY_TASK_QUEUE. */
25
+ readonly taskQueue: "safety-check-task-queue";
26
+ /** Signal that wakes the workflow early (extension, check-in, stop, SOS). */
27
+ readonly changedSignal: "safetyCheckChanged";
28
+ /** Query returning the workflow's view of the next wake time. */
29
+ readonly stateQuery: "safetyCheckWorkflowState";
30
+ };
31
+ /** Workflow id for a Safety Check. One per check, ever - the id IS the idempotency key. */
32
+ export declare function safetyCheckWorkflowId(safetyCheckId: string): string;
33
+ /** Internal HTTP paths (not proxied by the gateway). */
34
+ export declare const SAFETY_INTERNAL_PATHS: {
35
+ /** clarion-safety: the one domain step the durable timer drives. */
36
+ readonly advanceCheck: (safetyCheckId: string) => string;
37
+ /** clarion-workflow-manager: start the timer for a check. */
38
+ readonly startWorkflow: "/safety-checks/workflows";
39
+ /** clarion-workflow-manager: wake the timer early. */
40
+ readonly signalWorkflow: (safetyCheckId: string) => string;
41
+ /** clarion-incident: raise the Safety SOS incident (idempotent per origin). */
42
+ readonly createSafetyAlertIncident: "/incidents/safety-alerts";
43
+ /** clarion-incident: which of these incident type ids are platform-managed system types. */
44
+ readonly classifyIncidentTypes: "/incident-types/classify";
45
+ /** clarion-gis private trips (tracked privately until an SOS shares them). */
46
+ readonly createPrivateTrip: "/trips/private";
47
+ readonly tripTrackPoints: (tripId: string) => string;
48
+ readonly shareTrip: (tripId: string) => string;
49
+ readonly stopPrivateTrip: (tripId: string) => string;
50
+ readonly tripSummary: (tripId: string) => string;
51
+ };
52
+ /**
53
+ * go_router locations in clarion_mobile that pushes deep-link to. A push route
54
+ * is an APP location, never an API path.
55
+ */
56
+ export declare const SAFETY_MOBILE_ROUTES: {
57
+ readonly active: "/safety-check/active";
58
+ readonly prompt: "/safety-check/prompt";
59
+ };
60
+ /** Redis keys clarion-safety owns. */
61
+ export declare const SAFETY_REDIS_KEYS: {
62
+ readonly sweeperLock: "safety:lock:sweeper";
63
+ readonly rateLimit: (userId: number, bucket: string) => string;
64
+ };