grm-shared-library 1.1.188 → 1.1.190

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 (121) 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 +13 -0
  4. package/dist/cjs/kafka/topics.js.map +1 -1
  5. package/dist/cjs/modules/common/constants/service.const.js +1 -0
  6. package/dist/cjs/modules/common/constants/service.const.js.map +1 -1
  7. package/dist/cjs/modules/socket/enums/redis-channel-name.enum.js +1 -0
  8. package/dist/cjs/modules/socket/enums/redis-channel-name.enum.js.map +1 -1
  9. package/dist/cjs/modules/socket/enums/socket-event-name.enum.js +5 -0
  10. package/dist/cjs/modules/socket/enums/socket-event-name.enum.js.map +1 -1
  11. package/dist/cjs/modules/tracking/constants/tracking-kafka.const.js +48 -0
  12. package/dist/cjs/modules/tracking/constants/tracking-kafka.const.js.map +1 -0
  13. package/dist/cjs/modules/tracking/enums/tracking-connection-status.enum.js +27 -0
  14. package/dist/cjs/modules/tracking/enums/tracking-connection-status.enum.js.map +1 -0
  15. package/dist/cjs/modules/tracking/enums/tracking-event-quality.enum.js +22 -0
  16. package/dist/cjs/modules/tracking/enums/tracking-event-quality.enum.js.map +1 -0
  17. package/dist/cjs/modules/tracking/enums/tracking-provider-code.enum.js +28 -0
  18. package/dist/cjs/modules/tracking/enums/tracking-provider-code.enum.js.map +1 -0
  19. package/dist/cjs/modules/tracking/enums/tracking-transport-type.enum.js +22 -0
  20. package/dist/cjs/modules/tracking/enums/tracking-transport-type.enum.js.map +1 -0
  21. package/dist/cjs/modules/tracking/enums/tracking-unit-online-status.enum.js +18 -0
  22. package/dist/cjs/modules/tracking/enums/tracking-unit-online-status.enum.js.map +1 -0
  23. package/dist/cjs/modules/tracking/index.js +40 -0
  24. package/dist/cjs/modules/tracking/index.js.map +1 -0
  25. package/dist/cjs/modules/tracking/interfaces/response-unit-lifecycle-events.js +3 -0
  26. package/dist/cjs/modules/tracking/interfaces/response-unit-lifecycle-events.js.map +1 -0
  27. package/dist/cjs/modules/tracking/interfaces/response-unit-position-event-v1.js +3 -0
  28. package/dist/cjs/modules/tracking/interfaces/response-unit-position-event-v1.js.map +1 -0
  29. package/dist/cjs/modules/tracking/interfaces/response-unit-status-event-v1.js +3 -0
  30. package/dist/cjs/modules/tracking/interfaces/response-unit-status-event-v1.js.map +1 -0
  31. package/dist/cjs/modules/tracking/interfaces/tracking-device-unmapped-event-v1.js +3 -0
  32. package/dist/cjs/modules/tracking/interfaces/tracking-device-unmapped-event-v1.js.map +1 -0
  33. package/dist/cjs/modules/tracking/interfaces/tracking-ingestion-error-event-v1.js +3 -0
  34. package/dist/cjs/modules/tracking/interfaces/tracking-ingestion-error-event-v1.js.map +1 -0
  35. package/dist/cjs/modules/tracking/interfaces/tracking-position-quality-flags.js +3 -0
  36. package/dist/cjs/modules/tracking/interfaces/tracking-position-quality-flags.js.map +1 -0
  37. package/dist/cjs/modules/tracking/interfaces/tracking-provider-health-event-v1.js +3 -0
  38. package/dist/cjs/modules/tracking/interfaces/tracking-provider-health-event-v1.js.map +1 -0
  39. package/dist/cjs/modules/tracking/interfaces/tracking-realtime-envelope.js +3 -0
  40. package/dist/cjs/modules/tracking/interfaces/tracking-realtime-envelope.js.map +1 -0
  41. package/dist/cjs/modules/tracking/interfaces/tracking-socket-payloads.js +3 -0
  42. package/dist/cjs/modules/tracking/interfaces/tracking-socket-payloads.js.map +1 -0
  43. package/dist/cjs/modules/tracking/interfaces/tracking-unit-current-state.js +3 -0
  44. package/dist/cjs/modules/tracking/interfaces/tracking-unit-current-state.js.map +1 -0
  45. package/dist/cjs/modules/tracking/utils/tracking-event-id.util.js +31 -0
  46. package/dist/cjs/modules/tracking/utils/tracking-event-id.util.js.map +1 -0
  47. package/dist/cjs/modules/tracking/utils/tracking-validation.util.js +101 -0
  48. package/dist/cjs/modules/tracking/utils/tracking-validation.util.js.map +1 -0
  49. package/dist/esm/index.js +1 -0
  50. package/dist/esm/index.js.map +1 -1
  51. package/dist/esm/kafka/topics.js +13 -0
  52. package/dist/esm/kafka/topics.js.map +1 -1
  53. package/dist/esm/modules/common/constants/service.const.js +1 -0
  54. package/dist/esm/modules/common/constants/service.const.js.map +1 -1
  55. package/dist/esm/modules/socket/enums/redis-channel-name.enum.js +1 -0
  56. package/dist/esm/modules/socket/enums/redis-channel-name.enum.js.map +1 -1
  57. package/dist/esm/modules/socket/enums/socket-event-name.enum.js +5 -0
  58. package/dist/esm/modules/socket/enums/socket-event-name.enum.js.map +1 -1
  59. package/dist/esm/modules/tracking/constants/tracking-kafka.const.js +45 -0
  60. package/dist/esm/modules/tracking/constants/tracking-kafka.const.js.map +1 -0
  61. package/dist/esm/modules/tracking/enums/tracking-connection-status.enum.js +24 -0
  62. package/dist/esm/modules/tracking/enums/tracking-connection-status.enum.js.map +1 -0
  63. package/dist/esm/modules/tracking/enums/tracking-event-quality.enum.js +19 -0
  64. package/dist/esm/modules/tracking/enums/tracking-event-quality.enum.js.map +1 -0
  65. package/dist/esm/modules/tracking/enums/tracking-provider-code.enum.js +25 -0
  66. package/dist/esm/modules/tracking/enums/tracking-provider-code.enum.js.map +1 -0
  67. package/dist/esm/modules/tracking/enums/tracking-transport-type.enum.js +19 -0
  68. package/dist/esm/modules/tracking/enums/tracking-transport-type.enum.js.map +1 -0
  69. package/dist/esm/modules/tracking/enums/tracking-unit-online-status.enum.js +15 -0
  70. package/dist/esm/modules/tracking/enums/tracking-unit-online-status.enum.js.map +1 -0
  71. package/dist/esm/modules/tracking/index.js +24 -0
  72. package/dist/esm/modules/tracking/index.js.map +1 -0
  73. package/dist/esm/modules/tracking/interfaces/response-unit-lifecycle-events.js +2 -0
  74. package/dist/esm/modules/tracking/interfaces/response-unit-lifecycle-events.js.map +1 -0
  75. package/dist/esm/modules/tracking/interfaces/response-unit-position-event-v1.js +2 -0
  76. package/dist/esm/modules/tracking/interfaces/response-unit-position-event-v1.js.map +1 -0
  77. package/dist/esm/modules/tracking/interfaces/response-unit-status-event-v1.js +2 -0
  78. package/dist/esm/modules/tracking/interfaces/response-unit-status-event-v1.js.map +1 -0
  79. package/dist/esm/modules/tracking/interfaces/tracking-device-unmapped-event-v1.js +2 -0
  80. package/dist/esm/modules/tracking/interfaces/tracking-device-unmapped-event-v1.js.map +1 -0
  81. package/dist/esm/modules/tracking/interfaces/tracking-ingestion-error-event-v1.js +2 -0
  82. package/dist/esm/modules/tracking/interfaces/tracking-ingestion-error-event-v1.js.map +1 -0
  83. package/dist/esm/modules/tracking/interfaces/tracking-position-quality-flags.js +2 -0
  84. package/dist/esm/modules/tracking/interfaces/tracking-position-quality-flags.js.map +1 -0
  85. package/dist/esm/modules/tracking/interfaces/tracking-provider-health-event-v1.js +2 -0
  86. package/dist/esm/modules/tracking/interfaces/tracking-provider-health-event-v1.js.map +1 -0
  87. package/dist/esm/modules/tracking/interfaces/tracking-realtime-envelope.js +2 -0
  88. package/dist/esm/modules/tracking/interfaces/tracking-realtime-envelope.js.map +1 -0
  89. package/dist/esm/modules/tracking/interfaces/tracking-socket-payloads.js +2 -0
  90. package/dist/esm/modules/tracking/interfaces/tracking-socket-payloads.js.map +1 -0
  91. package/dist/esm/modules/tracking/interfaces/tracking-unit-current-state.js +2 -0
  92. package/dist/esm/modules/tracking/interfaces/tracking-unit-current-state.js.map +1 -0
  93. package/dist/esm/modules/tracking/utils/tracking-event-id.util.js +27 -0
  94. package/dist/esm/modules/tracking/utils/tracking-event-id.util.js.map +1 -0
  95. package/dist/esm/modules/tracking/utils/tracking-validation.util.js +93 -0
  96. package/dist/esm/modules/tracking/utils/tracking-validation.util.js.map +1 -0
  97. package/dist/types/index.d.ts +1 -0
  98. package/dist/types/kafka/topics.d.ts +10 -0
  99. package/dist/types/modules/common/constants/service.const.d.ts +4 -0
  100. package/dist/types/modules/socket/enums/redis-channel-name.enum.d.ts +2 -1
  101. package/dist/types/modules/socket/enums/socket-event-name.enum.d.ts +5 -1
  102. package/dist/types/modules/tracking/constants/tracking-kafka.const.d.ts +43 -0
  103. package/dist/types/modules/tracking/enums/tracking-connection-status.enum.d.ts +22 -0
  104. package/dist/types/modules/tracking/enums/tracking-event-quality.enum.d.ts +17 -0
  105. package/dist/types/modules/tracking/enums/tracking-provider-code.enum.d.ts +23 -0
  106. package/dist/types/modules/tracking/enums/tracking-transport-type.enum.d.ts +17 -0
  107. package/dist/types/modules/tracking/enums/tracking-unit-online-status.enum.d.ts +13 -0
  108. package/dist/types/modules/tracking/index.d.ts +18 -0
  109. package/dist/types/modules/tracking/interfaces/response-unit-lifecycle-events.d.ts +48 -0
  110. package/dist/types/modules/tracking/interfaces/response-unit-position-event-v1.d.ts +62 -0
  111. package/dist/types/modules/tracking/interfaces/response-unit-status-event-v1.d.ts +23 -0
  112. package/dist/types/modules/tracking/interfaces/tracking-device-unmapped-event-v1.d.ts +25 -0
  113. package/dist/types/modules/tracking/interfaces/tracking-ingestion-error-event-v1.d.ts +27 -0
  114. package/dist/types/modules/tracking/interfaces/tracking-position-quality-flags.d.ts +22 -0
  115. package/dist/types/modules/tracking/interfaces/tracking-provider-health-event-v1.d.ts +27 -0
  116. package/dist/types/modules/tracking/interfaces/tracking-realtime-envelope.d.ts +32 -0
  117. package/dist/types/modules/tracking/interfaces/tracking-socket-payloads.d.ts +53 -0
  118. package/dist/types/modules/tracking/interfaces/tracking-unit-current-state.d.ts +27 -0
  119. package/dist/types/modules/tracking/utils/tracking-event-id.util.d.ts +27 -0
  120. package/dist/types/modules/tracking/utils/tracking-validation.util.d.ts +40 -0
  121. package/package.json +70 -70
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Lifecycle state of a provider connection as observed by the connector worker.
3
+ * Surfaced in provider-health events and the provider-connection REST resource.
4
+ */
5
+ export declare enum TrackingConnectionStatus {
6
+ /** Administratively disabled — the worker will not attempt to connect. */
7
+ DISABLED = "DISABLED",
8
+ /** Not currently connected (idle, or between reconnect attempts). */
9
+ DISCONNECTED = "DISCONNECTED",
10
+ /** Transport handshake in progress. */
11
+ CONNECTING = "CONNECTING",
12
+ /** Transport is up; provider authentication / subscription in progress. */
13
+ AUTHENTICATING = "AUTHENTICATING",
14
+ /** Authenticated, subscribed and receiving (or ready to receive) telemetry. */
15
+ CONNECTED = "CONNECTED",
16
+ /** Connected but unhealthy (e.g. no telemetry for longer than expected). */
17
+ DEGRADED = "DEGRADED",
18
+ /** Provider rejected the credentials — a config problem, not a network blip. */
19
+ AUTHENTICATION_FAILED = "AUTHENTICATION_FAILED",
20
+ /** Non-auth error state (transport failure, protocol error, etc.). */
21
+ ERROR = "ERROR"
22
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Coarse classification of an ingested location, used for diagnostics and to
3
+ * decide whether an event updates current state (only fresh, in-order, valid
4
+ * events do). Fine-grained booleans live in {@link TrackingPositionQualityFlags}.
5
+ */
6
+ export declare enum TrackingEventQuality {
7
+ /** Valid, fresh and in order. */
8
+ GOOD = "GOOD",
9
+ /** Already seen (same deterministic eventId). */
10
+ DUPLICATE = "DUPLICATE",
11
+ /** Older than the current state for this unit. */
12
+ OUT_OF_ORDER = "OUT_OF_ORDER",
13
+ /** Coordinates outside the valid WGS84 range. */
14
+ INVALID_COORDINATES = "INVALID_COORDINATES",
15
+ /** Timestamp missing, unparseable, or outside the accepted tolerance. */
16
+ INVALID_TIMESTAMP = "INVALID_TIMESTAMP"
17
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Identifies the third-party tracking platform a provider connection integrates
3
+ * with. Provider-neutral: the core ingestion pipeline, tenant model, device
4
+ * bindings and canonical events never branch on a specific provider — only the
5
+ * per-provider adapter inside clarion-response-tracking understands the raw
6
+ * wire format.
7
+ *
8
+ * Only {@link TrackingProviderCode.TELOX} has a working adapter in Phase 1. The
9
+ * remaining values are reserved so future adapters can be added without changing
10
+ * the shared contracts, database columns or Kafka events.
11
+ */
12
+ export declare enum TrackingProviderCode {
13
+ /** Telox WebSocket platform (G4S Phase 1 integration). */
14
+ TELOX = "TELOX",
15
+ /** Wialon (reserved — not implemented in Phase 1). */
16
+ WIALON = "WIALON",
17
+ /** Teltonika direct device ingestion (reserved — not implemented in Phase 1). */
18
+ TELTONIKA = "TELTONIKA",
19
+ /** Generic WebSocket adapter (reserved). */
20
+ GENERIC_WEBSOCKET = "GENERIC_WEBSOCKET",
21
+ /** Generic HTTP polling adapter (reserved). */
22
+ GENERIC_HTTP_POLLING = "GENERIC_HTTP_POLLING"
23
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * How a provider connection physically transports telemetry into
3
+ * clarion-response-tracking. Phase 1 implements only {@link WEBSOCKET} (Telox);
4
+ * the remaining values are reserved for future adapters.
5
+ */
6
+ export declare enum TrackingTransportType {
7
+ /** Outbound WebSocket client maintained by the connector worker (Telox). */
8
+ WEBSOCKET = "WEBSOCKET",
9
+ /** Outbound HTTP polling loop. */
10
+ HTTP_POLLING = "HTTP_POLLING",
11
+ /** Inbound TCP listener (direct device ingestion). */
12
+ TCP = "TCP",
13
+ /** Inbound UDP listener (direct device ingestion). */
14
+ UDP = "UDP",
15
+ /** MQTT subscription. */
16
+ MQTT = "MQTT"
17
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Freshness of a response unit's last known position, derived by the projector's
3
+ * scheduled status evaluator from the gap between "now" and the last event time,
4
+ * using per-connection stale/offline thresholds.
5
+ */
6
+ export declare enum TrackingUnitOnlineStatus {
7
+ /** Reporting within the configured stale threshold. */
8
+ ONLINE = "ONLINE",
9
+ /** No update within the stale threshold but within the offline threshold. */
10
+ STALE = "STALE",
11
+ /** No update within the offline threshold. */
12
+ OFFLINE = "OFFLINE"
13
+ }
@@ -0,0 +1,18 @@
1
+ export * from './enums/tracking-provider-code.enum';
2
+ export * from './enums/tracking-transport-type.enum';
3
+ export * from './enums/tracking-connection-status.enum';
4
+ export * from './enums/tracking-unit-online-status.enum';
5
+ export * from './enums/tracking-event-quality.enum';
6
+ export * from './interfaces/tracking-position-quality-flags';
7
+ export * from './interfaces/response-unit-position-event-v1';
8
+ export * from './interfaces/response-unit-status-event-v1';
9
+ export * from './interfaces/tracking-provider-health-event-v1';
10
+ export * from './interfaces/tracking-device-unmapped-event-v1';
11
+ export * from './interfaces/tracking-ingestion-error-event-v1';
12
+ export * from './interfaces/response-unit-lifecycle-events';
13
+ export * from './interfaces/tracking-unit-current-state';
14
+ export * from './interfaces/tracking-socket-payloads';
15
+ export * from './interfaces/tracking-realtime-envelope';
16
+ export * from './constants/tracking-kafka.const';
17
+ export * from './utils/tracking-event-id.util';
18
+ export * from './utils/tracking-validation.util';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Response-unit lifecycle events published by clarion-organization (source of
3
+ * truth) and consumed by clarion-response-tracking to keep its local read
4
+ * projection in sync. Versioned (schema v1), provider-neutral, and free of
5
+ * provider/tracking-specific data.
6
+ *
7
+ * `sourceUpdatedAt` is the authoritative "when the change happened upstream"
8
+ * timestamp used by the consumer for idempotent, monotonic (older-event-reject)
9
+ * projection updates. `occurredAt` is when the event itself was produced.
10
+ */
11
+ export interface ResponseUnitLifecycleEventBase {
12
+ schemaVersion: 1;
13
+ /** Stable/deterministic id per the producer's convention (dedup + audit). */
14
+ eventId: string;
15
+ responseUnitId: number;
16
+ organizationId: number;
17
+ controlCentreId: number | null;
18
+ /** ISO 8601 UTC — upstream change time (ordering key for the projection). */
19
+ sourceUpdatedAt: string;
20
+ /** ISO 8601 UTC — when this event was produced. */
21
+ occurredAt: string;
22
+ correlationId?: string;
23
+ }
24
+ /** Descriptive response-unit fields carried by create/update/status events. */
25
+ export interface ResponseUnitDescriptor {
26
+ name?: string | null;
27
+ registrationNumber?: string | null;
28
+ responseUnitType?: string | null;
29
+ operationalStatus?: string | null;
30
+ enabled?: boolean;
31
+ }
32
+ export interface ResponseUnitCreatedEventV1 extends ResponseUnitLifecycleEventBase, ResponseUnitDescriptor {
33
+ }
34
+ export interface ResponseUnitUpdatedEventV1 extends ResponseUnitLifecycleEventBase, ResponseUnitDescriptor {
35
+ }
36
+ export interface ResponseUnitStatusChangedEventV1 extends ResponseUnitLifecycleEventBase, ResponseUnitDescriptor {
37
+ /** Whether the unit is enabled after the change (explicit for status events). */
38
+ enabled: boolean;
39
+ }
40
+ export interface ResponseUnitControlCentreChangedEventV1 extends ResponseUnitLifecycleEventBase, ResponseUnitDescriptor {
41
+ /** The control centre the unit moved FROM (null if it had none). */
42
+ previousControlCentreId: number | null;
43
+ }
44
+ export interface ResponseUnitDeletedEventV1 extends ResponseUnitLifecycleEventBase {
45
+ deleted: true;
46
+ }
47
+ /** Union of all response-unit lifecycle events. */
48
+ export type ResponseUnitLifecycleEventV1 = ResponseUnitCreatedEventV1 | ResponseUnitUpdatedEventV1 | ResponseUnitStatusChangedEventV1 | ResponseUnitControlCentreChangedEventV1 | ResponseUnitDeletedEventV1;
@@ -0,0 +1,62 @@
1
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
2
+ /**
3
+ * Canonical, provider-neutral position event (schema v1).
4
+ *
5
+ * Produced by clarion-response-tracking after a raw provider location has been
6
+ * parsed, validated, normalized and bound to a Clarion response unit. Published
7
+ * on the `tracking.response-unit.position.v1` Kafka topic and consumed by the
8
+ * projector (history + current state) and any future tracking consumers.
9
+ *
10
+ * SECURITY: this contract is deliberately free of provider credentials, secret
11
+ * references, raw provider payloads and internal Kafka metadata. `organizationId`
12
+ * and `controlCentreId` are always sourced from trusted Clarion data (the device
13
+ * binding + response-unit projection), never from provider-supplied fields.
14
+ */
15
+ export interface ResponseUnitPositionEventV1 {
16
+ schemaVersion: 1;
17
+ /** Deterministic id (see buildTrackingEventId) — same fix ⇒ same id. */
18
+ eventId: string;
19
+ providerCode: TrackingProviderCode;
20
+ providerConnectionId: string;
21
+ organizationId: number;
22
+ controlCentreId: number;
23
+ responseUnitId: number;
24
+ externalUnitId: string;
25
+ externalDeviceId?: string;
26
+ imei?: string;
27
+ /** When the provider recorded the fix (ISO 8601, UTC). */
28
+ eventTime: string;
29
+ /** When Clarion received the message (ISO 8601, UTC). */
30
+ receivedAt: string;
31
+ position: {
32
+ latitude: number;
33
+ longitude: number;
34
+ altitudeMetres?: number;
35
+ accuracyMetres?: number;
36
+ };
37
+ motion: {
38
+ /** Normalized to kilometres per hour. */
39
+ speedKph?: number;
40
+ /** Degrees clockwise from true north, [0, 360). Omitted when unknown. */
41
+ courseDegrees?: number;
42
+ moving?: boolean;
43
+ ignitionOn?: boolean;
44
+ };
45
+ telemetry?: {
46
+ satellites?: number;
47
+ odometerKm?: number;
48
+ batteryPercentage?: number;
49
+ externalPowerVoltage?: number;
50
+ gsmSignalPercentage?: number;
51
+ };
52
+ providerStatus?: string;
53
+ quality: {
54
+ duplicate: boolean;
55
+ outOfOrder: boolean;
56
+ coordinatesValid: boolean;
57
+ };
58
+ /** Safe, non-sensitive raw values preserved for future re-normalization. */
59
+ providerMetadata?: Record<string, unknown>;
60
+ /** Correlation id for tracing across services. */
61
+ correlationId?: string;
62
+ }
@@ -0,0 +1,23 @@
1
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
2
+ import { TrackingUnitOnlineStatus } from '../enums/tracking-unit-online-status.enum';
3
+ /**
4
+ * Canonical online-status change event (schema v1). Emitted by the projector's
5
+ * status evaluator only when a unit's ONLINE/STALE/OFFLINE status actually
6
+ * changes, on `tracking.response-unit.status.v1`.
7
+ */
8
+ export interface ResponseUnitStatusEventV1 {
9
+ schemaVersion: 1;
10
+ eventId: string;
11
+ organizationId: number;
12
+ controlCentreId: number;
13
+ responseUnitId: number;
14
+ providerCode: TrackingProviderCode;
15
+ providerConnectionId: string;
16
+ previousStatus?: TrackingUnitOnlineStatus;
17
+ status: TrackingUnitOnlineStatus;
18
+ /** ISO 8601, UTC — the eventTime of the last position seen for this unit. */
19
+ lastEventTime?: string;
20
+ /** ISO 8601, UTC — when the evaluator computed this status. */
21
+ evaluatedAt: string;
22
+ correlationId?: string;
23
+ }
@@ -0,0 +1,25 @@
1
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
2
+ /**
3
+ * Emitted on `tracking.device.unmapped.v1` when telemetry arrives for an external
4
+ * unit that has no active device binding. Drives the administrative unmapped-unit
5
+ * projection. Never broadcast to ordinary tracking rooms.
6
+ *
7
+ * SECURITY: `payloadSummary` carries only safe, non-sensitive fields (e.g.
8
+ * coordinates, timestamp, nickname) — never credentials or the raw provider frame.
9
+ */
10
+ export interface TrackingDeviceUnmappedEventV1 {
11
+ schemaVersion: 1;
12
+ eventId: string;
13
+ providerCode: TrackingProviderCode;
14
+ providerConnectionId: string;
15
+ organizationId: number;
16
+ controlCentreId?: number;
17
+ externalUnitId: string;
18
+ externalNickname?: string;
19
+ firstSeenAt: string;
20
+ lastSeenAt: string;
21
+ occurrenceCount: number;
22
+ payloadSummary?: Record<string, unknown>;
23
+ evaluatedAt: string;
24
+ correlationId?: string;
25
+ }
@@ -0,0 +1,27 @@
1
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
2
+ /**
3
+ * Stage at which ingestion of a provider message/location failed.
4
+ */
5
+ export type TrackingIngestionStage = 'parse' | 'validate' | 'normalize' | 'resolve-binding' | 'persist-history' | 'update-current-state' | 'publish';
6
+ /**
7
+ * Emitted on `tracking.ingestion.error.v1` for observability when a message or
8
+ * a single location fails to ingest. One bad location must never terminate the
9
+ * connection nor block the other locations in the same frame.
10
+ *
11
+ * SECURITY: errorMessage must be sanitized before emission — no credentials,
12
+ * no raw provider frame, no tokens.
13
+ */
14
+ export interface TrackingIngestionErrorEventV1 {
15
+ schemaVersion: 1;
16
+ eventId: string;
17
+ providerCode: TrackingProviderCode;
18
+ providerConnectionId: string;
19
+ organizationId?: number;
20
+ controlCentreId?: number;
21
+ externalUnitId?: string;
22
+ stage: TrackingIngestionStage;
23
+ errorCode: string;
24
+ errorMessage: string;
25
+ occurredAt: string;
26
+ correlationId?: string;
27
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Fine-grained quality booleans attached to an ingested position. Kept
3
+ * provider-neutral; producers set what they can determine and leave the rest
4
+ * undefined. `duplicate`, `outOfOrder` and `coordinatesValid` are always set
5
+ * because the ingestion pipeline always evaluates them.
6
+ */
7
+ export interface TrackingPositionQualityFlags {
8
+ /** The same deterministic eventId was already ingested. */
9
+ duplicate: boolean;
10
+ /** eventTime is older than the current-state eventTime for this unit. */
11
+ outOfOrder: boolean;
12
+ /** Latitude/longitude are within valid WGS84 ranges. */
13
+ coordinatesValid: boolean;
14
+ /** eventTime parsed and fell within the accepted tolerance window. */
15
+ timestampValid?: boolean;
16
+ /** courseDegrees was present and within [0, 360). */
17
+ courseValid?: boolean;
18
+ /** speed parsed to a finite, non-negative value. */
19
+ speedValid?: boolean;
20
+ /** Distance/time since the previous fix implies an implausible jump. */
21
+ positionJumpSuspected?: boolean;
22
+ }
@@ -0,0 +1,27 @@
1
+ import { TrackingConnectionStatus } from '../enums/tracking-connection-status.enum';
2
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
3
+ /**
4
+ * Provider-connection health event (schema v1), emitted on
5
+ * `tracking.provider.health.v1` when a connection's status meaningfully changes
6
+ * (never on every heartbeat). Delivered to administrators only — never broadcast
7
+ * to ordinary tracking rooms.
8
+ *
9
+ * SECURITY: errorMessage is sanitized upstream; it must never contain the
10
+ * password, the full authentication request, secret references or tokens.
11
+ */
12
+ export interface TrackingProviderHealthEventV1 {
13
+ schemaVersion: 1;
14
+ eventId: string;
15
+ providerConnectionId: string;
16
+ providerCode: TrackingProviderCode;
17
+ organizationId: number;
18
+ controlCentreId?: number;
19
+ connectionStatus: TrackingConnectionStatus;
20
+ connectedAt?: string;
21
+ disconnectedAt?: string;
22
+ lastEventAt?: string;
23
+ errorCode?: string;
24
+ errorMessage?: string;
25
+ evaluatedAt: string;
26
+ correlationId?: string;
27
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The message clarion-response-tracking publishes to the Redis `realtime:tracking`
3
+ * channel for clarion-socket to fan out. Mirrors the flat newsfeed realtime
4
+ * envelope convention (deliberately simpler than the incident EventEnvelope).
5
+ *
6
+ * clarion-socket dedups on `eventId`, derives authorized rooms from
7
+ * `organizationId`/`controlCentreId`, and emits `payload` under the matching
8
+ * `SocketEventName` (position/status/removed/provider-health).
9
+ *
10
+ * SECURITY: `payload` is always one of the frontend-safe Tracking*SocketPayloadV1
11
+ * shapes — never a raw provider frame or anything carrying credentials.
12
+ */
13
+ export type TrackingRealtimeEventType = 'position' | 'status' | 'removed' | 'provider-health';
14
+ export interface TrackingRealtimeEnvelope<TPayload = unknown> {
15
+ /** Deterministic where possible; used by clarion-socket for dedup. */
16
+ eventId: string;
17
+ eventType: TrackingRealtimeEventType;
18
+ organizationId: number;
19
+ /** Absent for org-wide-only events; present to also target a CC room. */
20
+ controlCentreId?: number;
21
+ responseUnitId?: number;
22
+ /** ISO 8601, UTC. */
23
+ occurredAt: string;
24
+ /**
25
+ * True for provider-health events, which must only reach administrators —
26
+ * clarion-socket routes these to admin/role rooms, not org/cc tracking rooms.
27
+ */
28
+ adminOnly?: boolean;
29
+ payload: TPayload;
30
+ correlationId?: string;
31
+ sourceService: string;
32
+ }
@@ -0,0 +1,53 @@
1
+ import { TrackingConnectionStatus } from '../enums/tracking-connection-status.enum';
2
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
3
+ import { TrackingUnitOnlineStatus } from '../enums/tracking-unit-online-status.enum';
4
+ /**
5
+ * Frontend-safe payloads emitted to Socket.IO clients by clarion-socket.
6
+ *
7
+ * These are intentionally a minimal projection — no secretReference, no
8
+ * credentials, no raw provider frame, no internal Kafka metadata. clarion-socket
9
+ * emits exactly these shapes; the frontend mirror lives in clarion-shared-types.
10
+ */
11
+ export interface TrackingPositionSocketPayloadV1 {
12
+ responseUnitId: number;
13
+ organizationId: number;
14
+ controlCentreId: number;
15
+ eventTime: string;
16
+ receivedAt: string;
17
+ latitude: number;
18
+ longitude: number;
19
+ accuracyMetres?: number;
20
+ speedKph?: number;
21
+ /** Degrees clockwise from true north, [0, 360). Omitted when unknown. */
22
+ courseDegrees?: number;
23
+ moving?: boolean;
24
+ ignitionOn?: boolean;
25
+ status: TrackingUnitOnlineStatus;
26
+ }
27
+ export interface TrackingStatusSocketPayloadV1 {
28
+ responseUnitId: number;
29
+ organizationId: number;
30
+ controlCentreId: number;
31
+ status: TrackingUnitOnlineStatus;
32
+ previousStatus?: TrackingUnitOnlineStatus;
33
+ lastEventTime?: string;
34
+ evaluatedAt: string;
35
+ }
36
+ export interface TrackingRemovedSocketPayloadV1 {
37
+ responseUnitId: number;
38
+ organizationId: number;
39
+ controlCentreId: number;
40
+ /** Why the unit was removed (binding disabled/deleted, unit deleted, …). */
41
+ reason?: string;
42
+ evaluatedAt: string;
43
+ }
44
+ export interface TrackingProviderHealthSocketPayloadV1 {
45
+ providerConnectionId: string;
46
+ providerCode: TrackingProviderCode;
47
+ organizationId: number;
48
+ controlCentreId?: number;
49
+ connectionStatus: TrackingConnectionStatus;
50
+ lastEventAt?: string;
51
+ errorCode?: string;
52
+ evaluatedAt: string;
53
+ }
@@ -0,0 +1,27 @@
1
+ import { TrackingProviderCode } from '../enums/tracking-provider-code.enum';
2
+ import { TrackingUnitOnlineStatus } from '../enums/tracking-unit-online-status.enum';
3
+ /**
4
+ * Shape of the current-position projection held in Redis
5
+ * (`tracking:unit-state:{responseUnitId}`) and returned by the current-position
6
+ * REST endpoints. Frontend-safe: no credentials, no provider raw frame.
7
+ */
8
+ export interface TrackingUnitCurrentState {
9
+ organizationId: number;
10
+ controlCentreId: number;
11
+ responseUnitId: number;
12
+ providerCode: TrackingProviderCode;
13
+ providerConnectionId: string;
14
+ externalUnitId: string;
15
+ latitude: number;
16
+ longitude: number;
17
+ accuracyMetres?: number | null;
18
+ speedKph?: number | null;
19
+ courseDegrees?: number | null;
20
+ altitudeMetres?: number | null;
21
+ moving?: boolean | null;
22
+ ignitionOn?: boolean | null;
23
+ eventTime: string;
24
+ receivedAt: string;
25
+ lastPresenceAt?: string | null;
26
+ status: TrackingUnitOnlineStatus;
27
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Stable inputs from which a tracking event's id is derived. Chosen so that the
3
+ * SAME provider fix always yields the SAME id (idempotent history + dedup),
4
+ * while distinct fixes for the same unit yield distinct ids.
5
+ */
6
+ export interface TrackingEventIdParts {
7
+ providerConnectionId: string;
8
+ externalUnitId: string;
9
+ /** Provider event time as Unix epoch SECONDS. */
10
+ eventEpochSeconds: number;
11
+ latitude: number;
12
+ longitude: number;
13
+ }
14
+ /**
15
+ * Build a deterministic tracking event id (sha256 hex) from stable fix inputs.
16
+ *
17
+ * Coordinates are quantized to 6 decimal places (~0.11 m) so floating-point
18
+ * representation differences across services never split one physical fix into
19
+ * two ids. Epoch seconds are truncated to whole seconds.
20
+ */
21
+ export declare function buildTrackingEventId(parts: TrackingEventIdParts): string;
22
+ /**
23
+ * Kafka partition key for position/status events. Keying by
24
+ * `{organizationId}:{controlCentreId}:{responseUnitId}` guarantees per-unit
25
+ * ordering within a partition. Never use a random key for these events.
26
+ */
27
+ export declare function buildTrackingPartitionKey(organizationId: number, controlCentreId: number, responseUnitId: number): string;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Provider-neutral validation/normalization helpers shared by the ingestion
3
+ * pipeline (and reusable by tests). No provider-specific field names appear here.
4
+ */
5
+ /** WGS84 latitude range check. */
6
+ export declare function isValidLatitude(value: unknown): value is number;
7
+ /** WGS84 longitude range check. */
8
+ export declare function isValidLongitude(value: unknown): value is number;
9
+ /** A valid course is a finite number in [0, 360). */
10
+ export declare function isValidCourseDegrees(value: unknown): value is number;
11
+ /**
12
+ * Normalize a raw course/bearing value into degrees in [0, 360), or null when it
13
+ * cannot be trusted for rotation.
14
+ *
15
+ * - A raw value of exactly `unknownSentinel` (default -1) is treated as unknown.
16
+ * - When `divisor` > 1 the raw value is divided (e.g. 27306 / 100 = 273.06).
17
+ * - The result is wrapped into [0, 360); a non-finite result yields null.
18
+ *
19
+ * The divisor is NOT hardcoded to a provider's scale — callers pass the value
20
+ * they have configured/confirmed for that connection.
21
+ */
22
+ export declare function normalizeCourseDegrees(raw: number | null | undefined, divisor?: number, unknownSentinel?: number | null): number | null;
23
+ /** Supported provider speed units for normalization into km/h. */
24
+ export type TrackingSpeedUnit = 'KPH' | 'MPS' | 'MPH' | 'RAW';
25
+ /**
26
+ * Convert a raw speed into kilometres per hour given the source unit and an
27
+ * optional multiplier applied to the raw value first. Returns null for
28
+ * non-finite or negative inputs. `RAW` means "already km/h after the multiplier".
29
+ */
30
+ export declare function normalizeSpeedToKph(raw: number | null | undefined, unit?: TrackingSpeedUnit, multiplier?: number): number | null;
31
+ /**
32
+ * Validate a provider epoch-seconds timestamp against a tolerance window and
33
+ * convert to an ISO 8601 UTC string. Returns null when out of range/unparseable.
34
+ *
35
+ * @param epochSeconds provider timestamp in seconds
36
+ * @param nowMs current time in ms (injectable for deterministic tests)
37
+ * @param futureToleranceSeconds max seconds a fix may be ahead of now
38
+ * @param maxAgeSeconds max seconds a fix may be behind now (0/undefined = no limit)
39
+ */
40
+ export declare function epochSecondsToIsoUtc(epochSeconds: number | null | undefined, nowMs: number, futureToleranceSeconds?: number, maxAgeSeconds?: number): string | null;