@hipnation-truth/sdk 0.17.2 → 0.18.0

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/react.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { ConvexReactClient } from 'convex/react';
4
3
  import * as convex_browser from 'convex/browser';
5
4
  import { ConvexHttpClient } from 'convex/browser';
6
5
 
@@ -689,10 +688,20 @@ declare function useConversationMessages(input: {
689
688
  */
690
689
  type PermissionStatus = "granted" | "denied" | "undetermined" | "unknown";
691
690
  interface UseNotificationsOptions {
692
- /** Truth API base URL, e.g. https://app.truth.communication-hub.com */
693
- apiBaseUrl: string;
694
- /** `hn_live_*` API key for the caller's application. */
695
- apiKey: string;
691
+ /**
692
+ * Truth API base URL — e.g. `https://app.truth.communication-hub.com`.
693
+ * Optional when the hook is mounted under `<TruthProvider>`: the
694
+ * provider resolves the URL from the environment (production + uat →
695
+ * prod Lambda; everything else → sandbox). Pass an override to point
696
+ * at a per-PR Truth stage (e.g. `https://pr-132-app.sandbox...`).
697
+ */
698
+ apiBaseUrl?: string;
699
+ /**
700
+ * `hn_live_*` API key for the caller's application. Optional when
701
+ * provided via `<TruthProvider apiKey={...}>` — the SDK reads it from
702
+ * context so each hook call doesn't have to repeat the prop.
703
+ */
704
+ apiKey?: string;
696
705
  /** Current user id — used when registering the device. */
697
706
  userId: string | null | undefined;
698
707
  /** Optional app version string stored on the device row. */
@@ -733,6 +742,42 @@ interface UseNotificationsResult {
733
742
  setBadgeCount: (count: number) => Promise<void>;
734
743
  }
735
744
  declare function useNotifications(options: UseNotificationsOptions): UseNotificationsResult;
745
+ /**
746
+ * useNotificationsActions — context-aware factory for the REST-backed
747
+ * notification actions exposed by `NotificationsResource` (send,
748
+ * schedule, get/update preferences). Reads `apiBaseUrl` + `apiKey`
749
+ * from `<TruthProvider>` so call sites don't have to instantiate the
750
+ * resource with creds inline.
751
+ *
752
+ * Returns memoized callbacks so they're stable across re-renders.
753
+ */
754
+ interface UseNotificationsActions {
755
+ send: (input: {
756
+ userId: string;
757
+ title: string;
758
+ body: string;
759
+ data?: Record<string, unknown>;
760
+ badge?: number;
761
+ sound?: string;
762
+ }) => Promise<{
763
+ delivered: number;
764
+ failed?: number;
765
+ suppressed?: boolean;
766
+ suppressionReason?: string;
767
+ }>;
768
+ schedule: (input: {
769
+ userId: string;
770
+ title: string;
771
+ body: string;
772
+ scheduledAt: string;
773
+ data?: Record<string, unknown>;
774
+ }) => Promise<{
775
+ jobId: string;
776
+ }>;
777
+ getPreferences: (userId: string) => Promise<Record<string, unknown>>;
778
+ updatePreferences: (userId: string, prefs: Record<string, unknown>) => Promise<Record<string, unknown>>;
779
+ }
780
+ declare function useNotificationsActions(): UseNotificationsActions;
736
781
 
737
782
  /**
738
783
  * React hook for patient family-member lookup — Truth SDK.
@@ -1005,776 +1050,331 @@ declare function usePatientsByIds(ids: string[] | null | undefined): UseQueryRes
1005
1050
  */
1006
1051
  declare function usePatientsByPhones(phones: string[] | null | undefined): UseQueryResult<Record<string, Patient>>;
1007
1052
 
1008
- interface TruthProviderProps {
1009
- /** Truth environment — determines which Convex deployment to connect to */
1010
- environment?: string;
1011
- /** Override the Convex URL directly */
1012
- convexUrl?: string;
1013
- children: ReactNode;
1014
- }
1015
- declare function TruthProvider({ environment, convexUrl, children, }: TruthProviderProps): react.FunctionComponentElement<{
1016
- client: ConvexReactClient;
1017
- children?: React.ReactNode;
1018
- }>;
1019
-
1020
1053
  /**
1021
- * Reminder types scheduled conversation reminders.
1054
+ * Appointment interfaces for the Truth SDK.
1022
1055
  */
1023
- type ReminderStatus = "pending" | "triggered" | "cancelled";
1024
- interface Reminder {
1025
- _id: string;
1026
- conversationId: string;
1027
- remindAt: string;
1028
- status: ReminderStatus;
1029
- note?: string;
1030
- createdBy: string;
1056
+ /**
1057
+ * Normalized appointment record from the Truth platform.
1058
+ */
1059
+ interface Appointment {
1060
+ /** Truth platform appointment ID */
1061
+ id: string;
1062
+ /** Associated patient ID */
1063
+ patientId: string;
1064
+ /** Provider/practitioner ID */
1065
+ providerId?: string;
1066
+ /** Provider/practitioner name */
1067
+ providerName?: string;
1068
+ /** Appointment start time (ISO 8601) */
1069
+ startTime: string;
1070
+ /** Appointment end time (ISO 8601) */
1071
+ endTime: string;
1072
+ /** Appointment status */
1073
+ status: string;
1074
+ /** Appointment type or reason */
1075
+ appointmentType?: string;
1076
+ /** Visit reason or chief complaint */
1077
+ reason?: string;
1078
+ /** Location or facility name */
1079
+ location?: string;
1080
+ /** Source EHR system (e.g. "elation", "hint") */
1081
+ sourceSystem?: string;
1082
+ /** ID in the source EHR system */
1083
+ sourceId?: string;
1084
+ /** Associated organization/tenant ID */
1085
+ tenantId: string;
1086
+ /** ISO 8601 timestamp of record creation */
1031
1087
  createdAt: string;
1032
- triggeredAt?: string;
1033
- cancelledAt?: string;
1034
- }
1035
- interface ScheduleReminderInput {
1036
- conversationId: string;
1037
- remindAt: string | Date;
1038
- note?: string;
1039
- createdBy: string;
1088
+ /** ISO 8601 timestamp of last update */
1089
+ updatedAt: string;
1040
1090
  }
1041
- interface ScheduleReminderResult {
1042
- reminderId: string;
1043
- remindAt: string;
1091
+ /**
1092
+ * Options for listing appointments.
1093
+ */
1094
+ interface AppointmentListOptions {
1095
+ /** Filter by patient ID */
1096
+ patientId?: string;
1097
+ /** Filter by start date (ISO 8601 date string) */
1098
+ startDate?: string;
1099
+ /** Filter by end date (ISO 8601 date string) */
1100
+ endDate?: string;
1101
+ /** Filter by appointment status */
1102
+ status?: string;
1103
+ /** Maximum number of results to return */
1104
+ limit?: number;
1105
+ /** Cursor for pagination */
1106
+ cursor?: string;
1044
1107
  }
1045
1108
 
1046
1109
  /**
1047
- * React hooks for conversation reminders — bulk lookup keyed by
1048
- * conversation id. Wraps the public `reminders:listPendingByConversationIds`
1049
- * Convex query so CommHub's inbox can render the reminder clock icon
1050
- * with one reactive subscription for the entire visible list.
1051
- *
1052
- * Must be used within `<TruthProvider />` (see `./provider`).
1110
+ * Configuration interfaces for the Truth SDK.
1053
1111
  */
1054
-
1055
1112
  /**
1056
- * Subscribe to the latest pending reminder for each of the given
1057
- * conversation ids. Returns a `Record<conversationId, Reminder>` —
1058
- * conversations with no pending reminder are absent from the map.
1059
- *
1060
- * Pass an empty array (or `undefined`) to skip the query — useful while
1061
- * the inbox list is still loading.
1062
- *
1063
- * @example
1064
- * ```tsx
1065
- * const ids = conversations.map((c) => c.id);
1066
- * const { data: remindersByConv } = useRemindersForConversations(ids);
1067
- * const r = remindersByConv?.[conv.id]; // Reminder | undefined
1068
- * ```
1113
+ * Environment options for the Truth platform.
1069
1114
  */
1070
- declare function useRemindersForConversations(conversationIds: string[] | null | undefined): UseQueryResult<Record<string, Reminder>>;
1071
-
1115
+ declare const ENVIRONMENTS: {
1116
+ readonly local: "local";
1117
+ readonly staging: "staging";
1118
+ readonly stg: "stg";
1119
+ readonly sandbox: "sandbox";
1120
+ readonly uat: "uat";
1121
+ readonly production: "production";
1122
+ };
1123
+ type Environment = (typeof ENVIRONMENTS)[keyof typeof ENVIRONMENTS];
1072
1124
  /**
1073
- * React hooks for conversation tasks (My Tasks surface).
1074
- *
1075
- * Provides a reactive `useMutation` wrapper around the
1076
- * `conversationTasks:markSeen` Convex mutation so CommHub can replace
1077
- * `useMark_Event_Activity_SeenMutation` from `@/generated/graphql`
1078
- * with a Truth SDK equivalent without touching `react.ts` exports (the
1079
- * central agent wires those).
1080
- *
1081
- * Pattern mirrors the existing hooks in `./conversations.ts`:
1082
- * - `makeFunctionReference` for decoupled Convex references
1083
- * - SKIP sentinel for conditional execution
1084
- * - Returns a stable callback, not a live subscription
1085
- *
1086
- * Must be used within `<TruthProvider />`.
1125
+ * Configuration for initializing a TruthClient.
1087
1126
  */
1127
+ interface TruthClientConfig {
1128
+ /** API key for authenticating with the Truth platform (e.g. "hn_live_...") */
1129
+ apiKey: string;
1130
+ /** Target environment */
1131
+ environment: Environment;
1132
+ /** Override the default Convex URL for data access */
1133
+ convexUrl?: string;
1134
+ /** Event source identifier (e.g. "communication-hub.backend") */
1135
+ source?: string;
1136
+ /** Git SHA or version string for event source versioning */
1137
+ sourceVersion?: string;
1138
+ /** Default tenant (organization) ID for events */
1139
+ tenantId?: string;
1140
+ /** Number of events to buffer before flushing (default: 25) */
1141
+ batchSize?: number;
1142
+ /** Interval in milliseconds between automatic flushes (default: 5000) */
1143
+ flushIntervalMs?: number;
1144
+ /** Base URL for the Truth API (overrides environment-based default) */
1145
+ apiBaseUrl?: string;
1146
+ /**
1147
+ * Auto-register the service worker and subscribe to web push on init.
1148
+ * Only applies in browser environments with Push API support.
1149
+ * Default: true.
1150
+ */
1151
+ autoInitServiceWorker?: boolean;
1152
+ /** Path to the service worker file. Default: "/truth-sw.js" */
1153
+ serviceWorkerPath?: string;
1154
+ }
1088
1155
  /**
1089
- * Returns a stable `markSeen(taskId, userId)` callback backed by the
1090
- * `conversationTasks:markSeen` Convex mutation. Replaces the Hasura
1091
- * `useMark_Event_Activity_SeenMutation` in CommHub's My Tasks surface.
1092
- *
1093
- * @example
1094
- * ```tsx
1095
- * const markSeen = useConversationTaskMarkSeen();
1096
- *
1097
- * // When a task row is pressed:
1098
- * if (!task.seenBy.includes(userId)) {
1099
- * markSeen(task.id, userId).catch(console.error);
1100
- * }
1101
- * ```
1156
+ * Actor context attached to tracked events.
1102
1157
  */
1103
- declare function useConversationTaskMarkSeen(): (taskId: string, userId: string) => Promise<{
1104
- ok: true;
1105
- }>;
1158
+ interface ActorContext {
1159
+ actorId: string;
1160
+ actorType: "user" | "system" | "webhook";
1161
+ }
1162
+ /**
1163
+ * Paginated result wrapper for list operations.
1164
+ */
1165
+ interface PaginatedResult<T> {
1166
+ data: T[];
1167
+ cursor: string | null;
1168
+ hasMore: boolean;
1169
+ }
1106
1170
 
1107
1171
  /**
1108
- * Typed event definitions for the Truth Platform event store.
1172
+ * AppointmentResource provides data access to normalized appointment records
1173
+ * backed by Convex.
1174
+ */
1175
+
1176
+ declare class AppointmentResource {
1177
+ private readonly convex;
1178
+ constructor(convexClient: ConvexHttpClient);
1179
+ /**
1180
+ * Get an appointment by its Truth platform ID.
1181
+ */
1182
+ get(id: string): Promise<Appointment | null>;
1183
+ /**
1184
+ * List appointments with optional filters, pagination, and limit.
1185
+ */
1186
+ list(options?: AppointmentListOptions): Promise<PaginatedResult<Appointment>>;
1187
+ }
1188
+
1189
+ /**
1190
+ * AttachmentsResource — presigned S3 upload/download + Convex metadata.
1109
1191
  *
1110
- * All 26 event types from the Communication Hub -> Truth Event Store Contract.
1111
- * Events are grouped by domain and include typed payload interfaces.
1192
+ * Replaces CommHub's base64-in-Postgres attachment flow:
1193
+ * 1. client.attachments.createUploadUrl(...) presigned PUT URL
1194
+ * 2. Client PUTs bytes directly to S3
1195
+ * 3. client.attachments.record(...) → writes Convex metadata
1196
+ * 4. client.attachments.getDownloadUrl(s3Key) → presigned GET URL
1112
1197
  */
1113
- declare const CONVERSATION_EVENTS: {
1114
- readonly created: "conversation.created.v1";
1115
- readonly messageSent: "conversation.message_sent.v1";
1116
- readonly messageReceived: "conversation.message_received.v1";
1117
- readonly markedRead: "conversation.marked_read.v1";
1118
- readonly attachmentUploaded: "conversation.attachment_uploaded.v1";
1119
- readonly attachmentDownloaded: "conversation.attachment_downloaded.v1";
1120
- };
1121
- declare const CALL_EVENTS: {
1122
- readonly initiated: "call.initiated.v1";
1123
- readonly connected: "call.connected.v1";
1124
- readonly ended: "call.ended.v1";
1125
- readonly missed: "call.missed.v1";
1126
- };
1127
- declare const TASK_EVENTS: {
1128
- readonly created: "task.created.v1";
1129
- readonly assigned: "task.assigned.v1";
1130
- readonly statusChanged: "task.status_changed.v1";
1131
- };
1132
- declare const REMINDER_EVENTS: {
1133
- readonly scheduled: "reminder.scheduled.v1";
1134
- readonly triggered: "reminder.triggered.v1";
1135
- };
1136
- declare const TRANSLATION_EVENTS: {
1137
- readonly requested: "translation.requested.v1";
1138
- readonly completed: "translation.completed.v1";
1139
- };
1140
- declare const NOTIFICATION_EVENTS: {
1141
- readonly sent: "notification.sent.v1";
1142
- readonly delivered: "notification.delivered.v1";
1143
- readonly opened: "notification.opened.v1";
1144
- };
1145
- declare const PROVIDER_EVENTS: {
1146
- readonly syncStarted: "provider.sync_started.v1";
1147
- readonly syncSucceeded: "provider.sync_succeeded.v1";
1148
- readonly syncFailed: "provider.sync_failed.v1";
1149
- };
1150
- declare const AUTH_EVENTS: {
1151
- readonly loginSucceeded: "auth.login_succeeded.v1";
1152
- readonly loginFailed: "auth.login_failed.v1";
1153
- };
1154
- declare const SECURITY_EVENTS: {
1155
- readonly accessDenied: "security.access_denied.v1";
1156
- };
1157
- type ConversationEventType = (typeof CONVERSATION_EVENTS)[keyof typeof CONVERSATION_EVENTS];
1158
- type CallEventType = (typeof CALL_EVENTS)[keyof typeof CALL_EVENTS];
1159
- type TaskEventType = (typeof TASK_EVENTS)[keyof typeof TASK_EVENTS];
1160
- type ReminderEventType = (typeof REMINDER_EVENTS)[keyof typeof REMINDER_EVENTS];
1161
- type TranslationEventType = (typeof TRANSLATION_EVENTS)[keyof typeof TRANSLATION_EVENTS];
1162
- type NotificationEventType = (typeof NOTIFICATION_EVENTS)[keyof typeof NOTIFICATION_EVENTS];
1163
- type ProviderEventType = (typeof PROVIDER_EVENTS)[keyof typeof PROVIDER_EVENTS];
1164
- type AuthEventType = (typeof AUTH_EVENTS)[keyof typeof AUTH_EVENTS];
1165
- type SecurityEventType = (typeof SECURITY_EVENTS)[keyof typeof SECURITY_EVENTS];
1166
- /**
1167
- * Union of all 26 registered event type strings.
1168
- */
1169
- type EventType = ConversationEventType | CallEventType | TaskEventType | ReminderEventType | TranslationEventType | NotificationEventType | ProviderEventType | AuthEventType | SecurityEventType;
1170
- interface ConversationCreatedPayload {
1171
- channel: string;
1172
- origin_system: string;
1173
- participant_count: number;
1198
+
1199
+ interface CreateUploadUrlInput {
1200
+ fileName: string;
1201
+ mimeType: string;
1202
+ size: number;
1203
+ conversationId?: string;
1174
1204
  }
1175
- interface ConversationMessageSentPayload {
1176
- channel: string;
1177
- direction: string;
1178
- message_chars: number;
1179
- has_attachment: boolean;
1180
- provider_system: string;
1205
+ interface CreateUploadUrlResult {
1206
+ uploadUrl: string;
1207
+ s3Key: string;
1208
+ expiresIn: number;
1209
+ applicationId: string | null;
1181
1210
  }
1182
- interface ConversationMessageReceivedPayload {
1183
- channel: string;
1184
- direction: string;
1185
- message_chars: number;
1186
- provider_system: string;
1211
+ interface GetDownloadUrlResult {
1212
+ url: string;
1213
+ expiresIn: number;
1187
1214
  }
1188
- interface ConversationMarkedReadPayload {
1189
- read_by_actor_id: string;
1190
- unread_count_before: number;
1191
- unread_count_after: number;
1215
+ interface RecordAttachmentInput {
1216
+ s3Key: string;
1217
+ fileName: string;
1218
+ mimeType: string;
1219
+ size: number;
1220
+ conversationId?: string;
1221
+ uploadedBy: string;
1192
1222
  }
1193
- interface ConversationAttachmentUploadedPayload {
1194
- attachment_id: string;
1195
- mime_type: string;
1196
- size_bytes: number;
1197
- storage_class: string;
1223
+ interface Attachment {
1224
+ _id: string;
1225
+ s3Key: string;
1226
+ fileName: string;
1227
+ mimeType: string;
1228
+ size: number;
1229
+ conversationId?: string;
1230
+ uploadedBy: string;
1231
+ createdAt: string;
1198
1232
  }
1199
- interface ConversationAttachmentDownloadedPayload {
1200
- attachment_id: string;
1201
- download_actor_type: string;
1202
- access_path: string;
1233
+ declare class AttachmentsResource {
1234
+ private readonly baseUrl;
1235
+ private readonly apiKey;
1236
+ private readonly convex;
1237
+ constructor(apiBaseUrl: string, apiKey: string, convexClient: ConvexHttpClient);
1238
+ private post;
1239
+ createUploadUrl(input: CreateUploadUrlInput): Promise<CreateUploadUrlResult>;
1240
+ getDownloadUrl(s3Key: string, expiresIn?: number): Promise<GetDownloadUrlResult>;
1241
+ record(input: RecordAttachmentInput): Promise<{
1242
+ attachmentId: string;
1243
+ s3Key: string;
1244
+ }>;
1245
+ get(attachmentId: string): Promise<Attachment | null>;
1246
+ listByConversation(conversationId: string): Promise<Attachment[]>;
1247
+ /**
1248
+ * One-shot upload: presign → PUT to S3 → record in Convex → return a
1249
+ * 7-day signed download URL ready to embed in an outbound SMS. Caller
1250
+ * passes the resulting `downloadUrl` to `messages.dialpad.sendSms` (or
1251
+ * the new `messages.sendAttachmentMessage`) to actually deliver it.
1252
+ *
1253
+ * Replaces CommHub's NestJS `/send-attachment` controller in a single
1254
+ * SDK call — no base64 round-trip, no legacy `/attachments/:id/download`
1255
+ * REST endpoint required.
1256
+ */
1257
+ upload(input: {
1258
+ file: Blob | ArrayBuffer | Uint8Array;
1259
+ fileName: string;
1260
+ mimeType: string;
1261
+ size: number;
1262
+ conversationId?: string;
1263
+ uploadedBy: string;
1264
+ /** Download URL TTL in seconds. Default 7 days. */
1265
+ downloadExpiresIn?: number;
1266
+ }): Promise<{
1267
+ attachmentId: string;
1268
+ s3Key: string;
1269
+ downloadUrl: string;
1270
+ }>;
1203
1271
  }
1204
- interface CallInitiatedPayload {
1205
- direction: string;
1206
- provider_system: string;
1207
- from_number_ref: string;
1208
- to_number_ref: string;
1272
+
1273
+ /**
1274
+ * ConversationsResource — write methods that hang off a specific
1275
+ * conversation: notes, tasks, outbound messages.
1276
+ *
1277
+ * Replaces CommHub's `truthConversationApi.ts` raw-fetch wrappers so
1278
+ * the frontend goes through a typed SDK surface instead of building
1279
+ * URLs by hand.
1280
+ *
1281
+ * All methods proxy the matching oRPC procedures (`/conversations/*`)
1282
+ * via Truth's application-key auth. Errors surface as
1283
+ * `ConversationsError` with a status code so callers can distinguish
1284
+ * transport failures (status=0) from API rejections (status>=400).
1285
+ */
1286
+ /** Address a conversation by either Convex `_id` or the phonePair. */
1287
+ interface ConversationAddress {
1288
+ conversationId?: string;
1289
+ phonePair?: string;
1209
1290
  }
1210
- interface CallConnectedPayload {
1211
- provider_system: string;
1212
- ring_duration_ms: number;
1291
+ type ConversationTaskStatus = "pending" | "completed";
1292
+ type ConversationTaskPriority = "high" | "medium" | "low";
1293
+ interface CreateConversationNoteInput extends ConversationAddress {
1294
+ eventId?: string;
1295
+ author: string;
1296
+ content: string;
1297
+ status?: string;
1298
+ type?: string;
1213
1299
  }
1214
- interface CallEndedPayload {
1215
- provider_system: string;
1216
- duration_ms: number;
1217
- end_reason: string;
1218
- disposition: string;
1300
+ interface CreateConversationTaskInput extends ConversationAddress {
1301
+ eventId?: string;
1302
+ author: string;
1303
+ description: string;
1304
+ status?: ConversationTaskStatus;
1305
+ priority?: ConversationTaskPriority;
1306
+ assignee?: string;
1307
+ type?: string;
1219
1308
  }
1220
- interface CallMissedPayload {
1221
- provider_system: string;
1222
- miss_reason: string;
1309
+ interface SetConversationTaskStatusInput {
1310
+ taskId: string;
1311
+ status: ConversationTaskStatus;
1312
+ resolvedBy?: string;
1223
1313
  }
1224
- interface TaskCreatedPayload {
1225
- task_id: string;
1226
- created_by: string;
1227
- assigned_to: string;
1228
- priority: string;
1229
- due_at: string;
1314
+ interface UpdateConversationTaskInput {
1315
+ taskId: string;
1316
+ /** Conversation the task belongs to. Truth requires this on PATCH. */
1317
+ conversationId: string;
1318
+ /** Required by the Truth task router — see `messages/procedures/tasks.ts`. */
1319
+ author: string;
1320
+ description: string;
1321
+ /** Optional patch fields — pass only the ones you want to change. */
1322
+ priority?: ConversationTaskPriority;
1323
+ status?: ConversationTaskStatus;
1324
+ assignee?: string;
1325
+ type?: string;
1230
1326
  }
1231
- interface TaskAssignedPayload {
1232
- task_id: string;
1233
- assigned_to: string;
1234
- assigned_by: string;
1327
+ interface SendConversationMessageInput {
1328
+ fromNumber: string;
1329
+ toNumber: string;
1330
+ message?: string;
1331
+ media?: string;
1235
1332
  }
1236
- interface TaskStatusChangedPayload {
1237
- task_id: string;
1238
- status_from: string;
1239
- status_to: string;
1240
- changed_by: string;
1333
+ interface SendConversationMessageResult {
1334
+ id: number;
1335
+ messageStatus: string;
1336
+ direction: string;
1241
1337
  }
1242
- interface ReminderScheduledPayload {
1243
- reminder_id: string;
1244
- conversation_id: string;
1245
- scheduled_for: string;
1246
- scheduled_by: string;
1338
+ declare class ConversationNotesSubresource {
1339
+ private readonly post;
1340
+ constructor(post: <T>(path: string, body: unknown) => Promise<T>);
1341
+ /** Create a note on a conversation (addressed by id or phonePair). */
1342
+ create(input: CreateConversationNoteInput): Promise<{
1343
+ id: string;
1344
+ }>;
1247
1345
  }
1248
- interface ReminderTriggeredPayload {
1249
- reminder_id: string;
1250
- trigger_result: string;
1251
- notification_attempted: boolean;
1346
+ declare class ConversationTasksSubresource {
1347
+ private readonly post;
1348
+ private readonly patch;
1349
+ constructor(post: <T>(path: string, body: unknown) => Promise<T>, patch: <T>(path: string, body: unknown) => Promise<T>);
1350
+ /** Create a task on a conversation. */
1351
+ create(input: CreateConversationTaskInput): Promise<{
1352
+ id: string;
1353
+ }>;
1354
+ /** Mark a task pending or completed. */
1355
+ setStatus(input: SetConversationTaskStatusInput): Promise<{
1356
+ ok: true;
1357
+ }>;
1358
+ /**
1359
+ * Update task fields (priority, assignee, description, type). Wraps
1360
+ * `PATCH /api/conversations/tasks/{id}` so CommHub doesn't have to
1361
+ * direct-fetch for non-status field edits.
1362
+ */
1363
+ update(input: UpdateConversationTaskInput): Promise<{
1364
+ ok: true;
1365
+ }>;
1252
1366
  }
1253
- interface TranslationRequestedPayload {
1254
- target_language: string;
1255
- source_language: string;
1256
- char_count: number;
1257
- mode: string;
1258
- }
1259
- interface TranslationCompletedPayload {
1260
- target_language: string;
1261
- provider: string;
1262
- latency_ms: number;
1263
- success: boolean;
1264
- error_code?: string;
1265
- }
1266
- interface NotificationSentPayload {
1267
- notification_id: string;
1268
- channel: string;
1269
- platform: string;
1270
- recipient_ref: string;
1271
- success: boolean;
1272
- }
1273
- interface NotificationDeliveredPayload {
1274
- notification_id: string;
1275
- platform: string;
1276
- delivered_at: string;
1277
- }
1278
- interface NotificationOpenedPayload {
1279
- notification_id: string;
1280
- platform: string;
1281
- opened_at: string;
1282
- }
1283
- interface ProviderSyncStartedPayload {
1284
- provider_system: string;
1285
- operation: string;
1286
- scope: string;
1287
- batch_id: string;
1288
- }
1289
- interface ProviderSyncSucceededPayload {
1290
- provider_system: string;
1291
- operation: string;
1292
- batch_id: string;
1293
- records_processed: number;
1294
- duration_ms: number;
1295
- }
1296
- interface ProviderSyncFailedPayload {
1297
- provider_system: string;
1298
- operation: string;
1299
- batch_id: string;
1300
- error_code: string;
1301
- retryable: boolean;
1302
- }
1303
- interface AuthLoginSucceededPayload {
1304
- auth_provider: string;
1305
- platform: string;
1306
- session_ref: string;
1307
- }
1308
- interface AuthLoginFailedPayload {
1309
- auth_provider: string;
1310
- platform: string;
1311
- failure_code: string;
1312
- }
1313
- interface SecurityAccessDeniedPayload {
1314
- resource: string;
1315
- policy: string;
1316
- reason_code: string;
1317
- actor_id: string;
1318
- }
1319
- /**
1320
- * Maps each event type string to its required payload interface.
1321
- */
1322
- interface EventPayloadMap {
1323
- "conversation.created.v1": ConversationCreatedPayload;
1324
- "conversation.message_sent.v1": ConversationMessageSentPayload;
1325
- "conversation.message_received.v1": ConversationMessageReceivedPayload;
1326
- "conversation.marked_read.v1": ConversationMarkedReadPayload;
1327
- "conversation.attachment_uploaded.v1": ConversationAttachmentUploadedPayload;
1328
- "conversation.attachment_downloaded.v1": ConversationAttachmentDownloadedPayload;
1329
- "call.initiated.v1": CallInitiatedPayload;
1330
- "call.connected.v1": CallConnectedPayload;
1331
- "call.ended.v1": CallEndedPayload;
1332
- "call.missed.v1": CallMissedPayload;
1333
- "task.created.v1": TaskCreatedPayload;
1334
- "task.assigned.v1": TaskAssignedPayload;
1335
- "task.status_changed.v1": TaskStatusChangedPayload;
1336
- "reminder.scheduled.v1": ReminderScheduledPayload;
1337
- "reminder.triggered.v1": ReminderTriggeredPayload;
1338
- "translation.requested.v1": TranslationRequestedPayload;
1339
- "translation.completed.v1": TranslationCompletedPayload;
1340
- "notification.sent.v1": NotificationSentPayload;
1341
- "notification.delivered.v1": NotificationDeliveredPayload;
1342
- "notification.opened.v1": NotificationOpenedPayload;
1343
- "provider.sync_started.v1": ProviderSyncStartedPayload;
1344
- "provider.sync_succeeded.v1": ProviderSyncSucceededPayload;
1345
- "provider.sync_failed.v1": ProviderSyncFailedPayload;
1346
- "auth.login_succeeded.v1": AuthLoginSucceededPayload;
1347
- "auth.login_failed.v1": AuthLoginFailedPayload;
1348
- "security.access_denied.v1": SecurityAccessDeniedPayload;
1349
- }
1350
- /**
1351
- * Subject references for the event. Uses tokenized references only -- no PHI.
1352
- */
1353
- interface EventSubject {
1354
- patient_ref?: string;
1355
- conversation_id?: string;
1356
- task_id?: string;
1357
- call_id?: string;
1358
- }
1359
- /**
1360
- * Actor who triggered the event.
1361
- */
1362
- interface EventActor {
1363
- actor_id: string;
1364
- actor_type: "user" | "system" | "webhook";
1365
- }
1366
- /**
1367
- * Compliance metadata for the event.
1368
- */
1369
- interface EventCompliance {
1370
- pii_level: "none" | "limited" | "full";
1371
- contains_phi: boolean;
1372
- consent_context: string;
1373
- retention_class: string;
1374
- }
1375
- /**
1376
- * Optional overrides when calling truth.track().
1377
- */
1378
- interface TrackOptions {
1379
- /** Override the default actor for this event */
1380
- actor?: EventActor;
1381
- /** Subject references for this event */
1382
- subject?: EventSubject;
1383
- /** Compliance metadata for this event */
1384
- compliance?: EventCompliance;
1385
- /** Override the default tenant ID for this event */
1386
- tenantId?: string;
1387
- /** Override the occurred_at timestamp (ISO 8601) */
1388
- occurredAt?: string;
1389
- }
1390
-
1391
- /**
1392
- * Configuration interfaces for the Truth SDK.
1393
- */
1394
- /**
1395
- * Environment options for the Truth platform.
1396
- */
1397
- declare const ENVIRONMENTS: {
1398
- readonly local: "local";
1399
- readonly staging: "staging";
1400
- readonly stg: "stg";
1401
- readonly sandbox: "sandbox";
1402
- readonly uat: "uat";
1403
- readonly production: "production";
1404
- };
1405
- type Environment = (typeof ENVIRONMENTS)[keyof typeof ENVIRONMENTS];
1406
- /**
1407
- * Configuration for initializing a TruthClient.
1408
- */
1409
- interface TruthClientConfig {
1410
- /** API key for authenticating with the Truth platform (e.g. "hn_live_...") */
1411
- apiKey: string;
1412
- /** Target environment */
1413
- environment: Environment;
1414
- /** Override the default Convex URL for data access */
1415
- convexUrl?: string;
1416
- /** Event source identifier (e.g. "communication-hub.backend") */
1417
- source?: string;
1418
- /** Git SHA or version string for event source versioning */
1419
- sourceVersion?: string;
1420
- /** Default tenant (organization) ID for events */
1421
- tenantId?: string;
1422
- /** Number of events to buffer before flushing (default: 25) */
1423
- batchSize?: number;
1424
- /** Interval in milliseconds between automatic flushes (default: 5000) */
1425
- flushIntervalMs?: number;
1426
- /** Base URL for the Truth API (overrides environment-based default) */
1427
- apiBaseUrl?: string;
1428
- /**
1429
- * Auto-register the service worker and subscribe to web push on init.
1430
- * Only applies in browser environments with Push API support.
1431
- * Default: true.
1432
- */
1433
- autoInitServiceWorker?: boolean;
1434
- /** Path to the service worker file. Default: "/truth-sw.js" */
1435
- serviceWorkerPath?: string;
1436
- }
1437
- /**
1438
- * Actor context attached to tracked events.
1439
- */
1440
- interface ActorContext {
1441
- actorId: string;
1442
- actorType: "user" | "system" | "webhook";
1443
- }
1444
- /**
1445
- * Paginated result wrapper for list operations.
1446
- */
1447
- interface PaginatedResult<T> {
1448
- data: T[];
1449
- cursor: string | null;
1450
- hasMore: boolean;
1451
- }
1452
-
1453
- interface TruthTrackingContextValue {
1454
- track: <T extends EventType>(eventType: T, payload: EventPayloadMap[T], options?: TrackOptions) => void;
1455
- identify: (actorId: string, actorType: ActorContext["actorType"]) => void;
1456
- }
1457
- interface TruthTrackingProviderProps {
1458
- /** Truth environment — determines API URL for event delivery */
1459
- environment?: string;
1460
- /** Event source identifier */
1461
- source?: string;
1462
- /** Source version (git SHA) */
1463
- sourceVersion?: string;
1464
- /** Default tenant ID */
1465
- tenantId?: string;
1466
- /** API key for authentication */
1467
- apiKey?: string;
1468
- children: ReactNode;
1469
- }
1470
- declare function TruthTrackingProvider({ environment, source, sourceVersion, tenantId, apiKey, children, }: TruthTrackingProviderProps): react.FunctionComponentElement<react.ProviderProps<TruthTrackingContextValue | null>>;
1471
- /**
1472
- * Access the Truth tracking context. Must be within a TruthTrackingProvider.
1473
- * Returns `{ track, identify }` for emitting events to Kinesis.
1474
- */
1475
- declare function useTruth(): TruthTrackingContextValue;
1476
-
1477
- /**
1478
- * UserSettingsResource — typed client for the Truth `userSettings` Convex
1479
- * table. Exposes the one mutation CommHub's Settings screen needs:
1480
- * `updateNotifications({ userId, notificationsEnabled })`.
1481
- *
1482
- * Server-side / imperative use:
1483
- * truth.userSettings.updateNotifications({ userId, notificationsEnabled: true })
1484
- *
1485
- * Reactive React use lives in `@hipnation-truth/sdk/react` via
1486
- * `useUserSettings`.
1487
- */
1488
-
1489
- interface UserSettings {
1490
- _id: string;
1491
- userId: string;
1492
- notificationsEnabled: boolean;
1493
- createdAt: string;
1494
- updatedAt: string;
1495
- }
1496
- interface UpdateNotificationsInput {
1497
- userId: string;
1498
- notificationsEnabled: boolean;
1499
- }
1500
- interface UpdateNotificationsResult {
1501
- action: "inserted" | "updated";
1502
- id: string;
1503
- }
1504
- declare class UserSettingsResource {
1505
- private readonly convex;
1506
- constructor(convex: ConvexHttpClient);
1507
- /**
1508
- * Upsert notification preferences for a user. Creates the row if it
1509
- * doesn't exist; patches `notificationsEnabled` + `updatedAt` otherwise.
1510
- */
1511
- updateNotifications(input: UpdateNotificationsInput): Promise<UpdateNotificationsResult>;
1512
- }
1513
-
1514
- /**
1515
- * useUserSettings — reactive hook for per-user notification preferences
1516
- * stored in the Truth `userSettings` Convex table.
1517
- *
1518
- * Must be used within `<TruthProvider />` (see `./provider`).
1519
- *
1520
- * @example
1521
- * ```tsx
1522
- * const { data: settings, loading } = useUserSettings(userId);
1523
- * // settings?.notificationsEnabled — boolean or undefined (no row yet)
1524
- * ```
1525
- */
1526
-
1527
- /**
1528
- * Subscribe to the `userSettings` row for `userId`. Returns `null` when
1529
- * no row exists (treat as all-defaults). Returns `undefined` while the
1530
- * Convex query is in-flight.
1531
- *
1532
- * Pass `null` or `undefined` as `userId` to skip the query (e.g. while
1533
- * auth is loading).
1534
- */
1535
- declare function useUserSettings(userId: string | null | undefined): UseQueryResult<UserSettings | null>;
1536
-
1537
- /**
1538
- * Appointment interfaces for the Truth SDK.
1539
- */
1540
- /**
1541
- * Normalized appointment record from the Truth platform.
1542
- */
1543
- interface Appointment {
1544
- /** Truth platform appointment ID */
1545
- id: string;
1546
- /** Associated patient ID */
1547
- patientId: string;
1548
- /** Provider/practitioner ID */
1549
- providerId?: string;
1550
- /** Provider/practitioner name */
1551
- providerName?: string;
1552
- /** Appointment start time (ISO 8601) */
1553
- startTime: string;
1554
- /** Appointment end time (ISO 8601) */
1555
- endTime: string;
1556
- /** Appointment status */
1557
- status: string;
1558
- /** Appointment type or reason */
1559
- appointmentType?: string;
1560
- /** Visit reason or chief complaint */
1561
- reason?: string;
1562
- /** Location or facility name */
1563
- location?: string;
1564
- /** Source EHR system (e.g. "elation", "hint") */
1565
- sourceSystem?: string;
1566
- /** ID in the source EHR system */
1567
- sourceId?: string;
1568
- /** Associated organization/tenant ID */
1569
- tenantId: string;
1570
- /** ISO 8601 timestamp of record creation */
1571
- createdAt: string;
1572
- /** ISO 8601 timestamp of last update */
1573
- updatedAt: string;
1574
- }
1575
- /**
1576
- * Options for listing appointments.
1577
- */
1578
- interface AppointmentListOptions {
1579
- /** Filter by patient ID */
1580
- patientId?: string;
1581
- /** Filter by start date (ISO 8601 date string) */
1582
- startDate?: string;
1583
- /** Filter by end date (ISO 8601 date string) */
1584
- endDate?: string;
1585
- /** Filter by appointment status */
1586
- status?: string;
1587
- /** Maximum number of results to return */
1588
- limit?: number;
1589
- /** Cursor for pagination */
1590
- cursor?: string;
1591
- }
1592
-
1593
- /**
1594
- * AppointmentResource provides data access to normalized appointment records
1595
- * backed by Convex.
1596
- */
1597
-
1598
- declare class AppointmentResource {
1599
- private readonly convex;
1600
- constructor(convexClient: ConvexHttpClient);
1601
- /**
1602
- * Get an appointment by its Truth platform ID.
1603
- */
1604
- get(id: string): Promise<Appointment | null>;
1605
- /**
1606
- * List appointments with optional filters, pagination, and limit.
1607
- */
1608
- list(options?: AppointmentListOptions): Promise<PaginatedResult<Appointment>>;
1609
- }
1610
-
1611
- /**
1612
- * AttachmentsResource — presigned S3 upload/download + Convex metadata.
1613
- *
1614
- * Replaces CommHub's base64-in-Postgres attachment flow:
1615
- * 1. client.attachments.createUploadUrl(...) → presigned PUT URL
1616
- * 2. Client PUTs bytes directly to S3
1617
- * 3. client.attachments.record(...) → writes Convex metadata
1618
- * 4. client.attachments.getDownloadUrl(s3Key) → presigned GET URL
1619
- */
1620
-
1621
- interface CreateUploadUrlInput {
1622
- fileName: string;
1623
- mimeType: string;
1624
- size: number;
1625
- conversationId?: string;
1626
- }
1627
- interface CreateUploadUrlResult {
1628
- uploadUrl: string;
1629
- s3Key: string;
1630
- expiresIn: number;
1631
- applicationId: string | null;
1632
- }
1633
- interface GetDownloadUrlResult {
1634
- url: string;
1635
- expiresIn: number;
1636
- }
1637
- interface RecordAttachmentInput {
1638
- s3Key: string;
1639
- fileName: string;
1640
- mimeType: string;
1641
- size: number;
1642
- conversationId?: string;
1643
- uploadedBy: string;
1644
- }
1645
- interface Attachment {
1646
- _id: string;
1647
- s3Key: string;
1648
- fileName: string;
1649
- mimeType: string;
1650
- size: number;
1651
- conversationId?: string;
1652
- uploadedBy: string;
1653
- createdAt: string;
1654
- }
1655
- declare class AttachmentsResource {
1656
- private readonly baseUrl;
1657
- private readonly apiKey;
1658
- private readonly convex;
1659
- constructor(apiBaseUrl: string, apiKey: string, convexClient: ConvexHttpClient);
1660
- private post;
1661
- createUploadUrl(input: CreateUploadUrlInput): Promise<CreateUploadUrlResult>;
1662
- getDownloadUrl(s3Key: string, expiresIn?: number): Promise<GetDownloadUrlResult>;
1663
- record(input: RecordAttachmentInput): Promise<{
1664
- attachmentId: string;
1665
- s3Key: string;
1666
- }>;
1667
- get(attachmentId: string): Promise<Attachment | null>;
1668
- listByConversation(conversationId: string): Promise<Attachment[]>;
1669
- /**
1670
- * One-shot upload: presign → PUT to S3 → record in Convex → return a
1671
- * 7-day signed download URL ready to embed in an outbound SMS. Caller
1672
- * passes the resulting `downloadUrl` to `messages.dialpad.sendSms` (or
1673
- * the new `messages.sendAttachmentMessage`) to actually deliver it.
1674
- *
1675
- * Replaces CommHub's NestJS `/send-attachment` controller in a single
1676
- * SDK call — no base64 round-trip, no legacy `/attachments/:id/download`
1677
- * REST endpoint required.
1678
- */
1679
- upload(input: {
1680
- file: Blob | ArrayBuffer | Uint8Array;
1681
- fileName: string;
1682
- mimeType: string;
1683
- size: number;
1684
- conversationId?: string;
1685
- uploadedBy: string;
1686
- /** Download URL TTL in seconds. Default 7 days. */
1687
- downloadExpiresIn?: number;
1688
- }): Promise<{
1689
- attachmentId: string;
1690
- s3Key: string;
1691
- downloadUrl: string;
1692
- }>;
1693
- }
1694
-
1695
- /**
1696
- * ConversationsResource — write methods that hang off a specific
1697
- * conversation: notes, tasks, outbound messages.
1698
- *
1699
- * Replaces CommHub's `truthConversationApi.ts` raw-fetch wrappers so
1700
- * the frontend goes through a typed SDK surface instead of building
1701
- * URLs by hand.
1702
- *
1703
- * All methods proxy the matching oRPC procedures (`/conversations/*`)
1704
- * via Truth's application-key auth. Errors surface as
1705
- * `ConversationsError` with a status code so callers can distinguish
1706
- * transport failures (status=0) from API rejections (status>=400).
1707
- */
1708
- /** Address a conversation by either Convex `_id` or the phonePair. */
1709
- interface ConversationAddress {
1710
- conversationId?: string;
1711
- phonePair?: string;
1712
- }
1713
- type ConversationTaskStatus = "pending" | "completed";
1714
- type ConversationTaskPriority = "high" | "medium" | "low";
1715
- interface CreateConversationNoteInput extends ConversationAddress {
1716
- eventId?: string;
1717
- author: string;
1718
- content: string;
1719
- status?: string;
1720
- type?: string;
1721
- }
1722
- interface CreateConversationTaskInput extends ConversationAddress {
1723
- eventId?: string;
1724
- author: string;
1725
- description: string;
1726
- status?: ConversationTaskStatus;
1727
- priority?: ConversationTaskPriority;
1728
- assignee?: string;
1729
- type?: string;
1730
- }
1731
- interface SetConversationTaskStatusInput {
1732
- taskId: string;
1733
- status: ConversationTaskStatus;
1734
- resolvedBy?: string;
1735
- }
1736
- interface SendConversationMessageInput {
1737
- fromNumber: string;
1738
- toNumber: string;
1739
- message?: string;
1740
- media?: string;
1741
- }
1742
- interface SendConversationMessageResult {
1743
- id: number;
1744
- messageStatus: string;
1745
- direction: string;
1746
- }
1747
- declare class ConversationNotesSubresource {
1748
- private readonly post;
1749
- constructor(post: <T>(path: string, body: unknown) => Promise<T>);
1750
- /** Create a note on a conversation (addressed by id or phonePair). */
1751
- create(input: CreateConversationNoteInput): Promise<{
1752
- id: string;
1753
- }>;
1754
- }
1755
- declare class ConversationTasksSubresource {
1756
- private readonly post;
1757
- constructor(post: <T>(path: string, body: unknown) => Promise<T>);
1758
- /** Create a task on a conversation. */
1759
- create(input: CreateConversationTaskInput): Promise<{
1760
- id: string;
1761
- }>;
1762
- /** Mark a task pending or completed. */
1763
- setStatus(input: SetConversationTaskStatusInput): Promise<{
1764
- ok: true;
1765
- }>;
1766
- }
1767
- declare class ConversationMessagesSubresource {
1768
- private readonly post;
1769
- constructor(post: <T>(path: string, body: unknown) => Promise<T>);
1770
- /**
1771
- * Send an outbound SMS / MMS via the typed `sendMessage` oRPC procedure.
1772
- *
1773
- * Prefer this over the generic Dialpad proxy (`messages.dialpad.sendSms`)
1774
- * — this hits the validated Truth route and consistently surfaces
1775
- * `ConversationsError` on failure.
1776
- */
1777
- send(input: SendConversationMessageInput): Promise<SendConversationMessageResult>;
1367
+ declare class ConversationMessagesSubresource {
1368
+ private readonly post;
1369
+ constructor(post: <T>(path: string, body: unknown) => Promise<T>);
1370
+ /**
1371
+ * Send an outbound SMS / MMS via the typed `sendMessage` oRPC procedure.
1372
+ *
1373
+ * Prefer this over the generic Dialpad proxy (`messages.dialpad.sendSms`)
1374
+ * — this hits the validated Truth route and consistently surfaces
1375
+ * `ConversationsError` on failure.
1376
+ */
1377
+ send(input: SendConversationMessageInput): Promise<SendConversationMessageResult>;
1778
1378
  }
1779
1379
  declare class ConversationsResource {
1780
1380
  readonly notes: ConversationNotesSubresource;
@@ -1817,6 +1417,13 @@ declare class ConversationsResource {
1817
1417
  cleared: number;
1818
1418
  }>;
1819
1419
  private postRequest;
1420
+ /**
1421
+ * PATCH variant of `postRequest`. Mirrors the timeout + API-key
1422
+ * handling so callers like `tasks.update()` don't need to roll their
1423
+ * own fetch. The Truth task router treats unknown methods as 405, so
1424
+ * a dedicated PATCH path is required.
1425
+ */
1426
+ private patchRequest;
1820
1427
  }
1821
1428
 
1822
1429
  /**
@@ -2078,437 +1685,784 @@ declare class NotesResource {
2078
1685
  * row to `elationSyncEvents`. Replaces CommHub's `pushNotesToElation`
2079
1686
  * Hasura action.
2080
1687
  */
2081
- pushConversationToElation(input: PushConversationToElationInput): Promise<PushConversationToElationResult>;
1688
+ pushConversationToElation(input: PushConversationToElationInput): Promise<PushConversationToElationResult>;
1689
+ }
1690
+
1691
+ /**
1692
+ * NotificationsResource — wraps Truth's /api/notifications/* endpoints.
1693
+ *
1694
+ * Server-side use (for example from a CommHub backend job or
1695
+ * another service): `truth.notifications.send({ userId, title, body })`.
1696
+ *
1697
+ * Client-side React usage lives in `@hipnation-truth/sdk/react` via
1698
+ * the `useNotifications` hook which mirrors `expo-notifications`.
1699
+ */
1700
+ type NotificationPlatform = "ios" | "android" | "web";
1701
+ interface RegisterDeviceInput {
1702
+ userId: string;
1703
+ platform: NotificationPlatform;
1704
+ nativeToken?: string;
1705
+ webPushSubscription?: {
1706
+ endpoint: string;
1707
+ keys: {
1708
+ p256dh: string;
1709
+ auth: string;
1710
+ };
1711
+ };
1712
+ appVersion?: string;
1713
+ osVersion?: string;
1714
+ locale?: string;
1715
+ timezone?: string;
1716
+ /**
1717
+ * iOS only — which APNs endpoint the `nativeToken` was issued
1718
+ * against. The token bytes don't carry this; it's determined by
1719
+ * the build's `aps-environment` entitlement
1720
+ * (`development` ⇒ sandbox, `production` ⇒ production). When the
1721
+ * consumer is an Expo app, detect via
1722
+ * `Application.getIosPushNotificationServiceEnvironmentAsync()`
1723
+ * from `expo-application` and pass the normalised value here.
1724
+ * Omitting this falls back to the application's default
1725
+ * `pushConfig.ios.environment` server-side.
1726
+ */
1727
+ apnsEnvironment?: "sandbox" | "production";
1728
+ }
1729
+ interface RegisterDeviceResult {
1730
+ deviceId: string;
1731
+ action: "inserted" | "updated";
1732
+ snsEndpointArn?: string;
1733
+ }
1734
+ interface UnregisterDeviceInput {
1735
+ nativeToken?: string;
1736
+ deviceId?: string;
1737
+ }
1738
+ interface SendNotificationInput {
1739
+ userId: string;
1740
+ title: string;
1741
+ body: string;
1742
+ data?: Record<string, unknown>;
1743
+ badge?: number;
1744
+ sound?: string;
1745
+ }
1746
+ interface SendNotificationResult {
1747
+ delivered: number;
1748
+ failed?: number;
1749
+ suppressed?: boolean;
1750
+ suppressionReason?: string;
1751
+ }
1752
+ interface NotificationPreferences {
1753
+ channels: {
1754
+ sms: boolean;
1755
+ push: boolean;
1756
+ email: boolean;
1757
+ inApp: boolean;
1758
+ };
1759
+ quietHours?: {
1760
+ enabled: boolean;
1761
+ start: string;
1762
+ end: string;
1763
+ timezone: string;
1764
+ };
1765
+ doNotDisturbUntil?: string;
1766
+ updatedAt: string;
1767
+ }
1768
+ interface UpdatePreferencesInput {
1769
+ userId: string;
1770
+ channels?: NotificationPreferences["channels"];
1771
+ quietHours?: NotificationPreferences["quietHours"];
1772
+ doNotDisturbUntil?: string | null;
1773
+ }
1774
+ interface ScheduleNotificationInput extends SendNotificationInput {
1775
+ /** ISO 8601 timestamp; must be strictly in the future. */
1776
+ scheduledAt: string;
1777
+ }
1778
+ interface ScheduleNotificationResult {
1779
+ jobId: string;
1780
+ scheduledAt: string;
1781
+ }
1782
+ interface CancelScheduledNotificationResult {
1783
+ cancelled: boolean;
1784
+ reason?: string;
1785
+ status?: string;
1786
+ }
1787
+ type ScheduledJobStatus = "pending" | "executed" | "cancelled" | "failed";
1788
+ interface ScheduledNotification {
1789
+ jobId: string;
1790
+ userId: string;
1791
+ title: string;
1792
+ body: string;
1793
+ data?: unknown;
1794
+ badge?: number;
1795
+ sound?: string;
1796
+ scheduledAt: string;
1797
+ status: ScheduledJobStatus;
1798
+ resultHistoryId?: string;
1799
+ errorMessage?: string;
1800
+ createdAt: string;
1801
+ }
1802
+ interface PushEventPayload {
1803
+ title: string;
1804
+ body: string;
1805
+ data?: unknown;
1806
+ }
1807
+ declare class NotificationsResource {
1808
+ private readonly baseUrl;
1809
+ private readonly apiKey;
1810
+ constructor(apiBaseUrl: string, apiKey: string);
1811
+ private post;
1812
+ private get;
1813
+ private delete;
1814
+ /**
1815
+ * Register a device (or refresh its metadata) for push delivery.
1816
+ * Safe to call repeatedly — the server dedupes by native token.
1817
+ */
1818
+ registerDevice(input: RegisterDeviceInput): Promise<RegisterDeviceResult>;
1819
+ /** Revoke a device — on sign-out or when the OS reports an invalid token. */
1820
+ unregisterDevice(input: UnregisterDeviceInput): Promise<{
1821
+ revoked: boolean;
1822
+ }>;
1823
+ /**
1824
+ * Send a push notification to every active device belonging to
1825
+ * `userId`. Honors the user's notificationPreferences (quiet hours,
1826
+ * DND, channel off) before publishing.
1827
+ */
1828
+ send(input: SendNotificationInput): Promise<SendNotificationResult>;
1829
+ /** Read a user's notification preferences. Returns defaults when no row exists. */
1830
+ getPreferences(userId: string): Promise<NotificationPreferences>;
1831
+ updatePreferences(input: UpdatePreferencesInput): Promise<{
1832
+ ok: boolean;
1833
+ }>;
1834
+ /**
1835
+ * Schedule a future push notification. Convex's native scheduler
1836
+ * fires the send at `scheduledAt` and runs the same delivery
1837
+ * pipeline as `send()` (preferences, devices, history audit).
1838
+ *
1839
+ * Throws `NotificationsError` with status 400 if `scheduledAt` is
1840
+ * not strictly in the future.
1841
+ */
1842
+ schedule(input: ScheduleNotificationInput): Promise<ScheduleNotificationResult>;
1843
+ /**
1844
+ * Cancel a pending scheduled notification. Returns `cancelled: false`
1845
+ * (no error) if the job has already executed, was previously
1846
+ * cancelled, or no longer exists — `reason` describes which case.
1847
+ */
1848
+ cancelScheduled(jobId: string): Promise<CancelScheduledNotificationResult>;
1849
+ /**
1850
+ * List scheduled notifications for a user — pending, executed,
1851
+ * cancelled, or failed. Most-recent first. Default limit 100.
1852
+ */
1853
+ listScheduled(userId: string, options?: {
1854
+ limit?: number;
1855
+ }): Promise<ScheduledNotification[]>;
1856
+ getVapidKey(): Promise<string | null>;
1857
+ onPushReceived(callback: (payload: PushEventPayload) => void): () => void;
1858
+ onPushTapped(callback: (payload: PushEventPayload) => void): () => void;
1859
+ }
1860
+
1861
+ /**
1862
+ * PatientDetailsResource — merged Hint + Elation patient lookups.
1863
+ *
1864
+ * Backed by the Truth API at /api/patients/details/*, authenticated with
1865
+ * X-API-Key. Replaces CommHub's getPatientDetails / getPatientBasicDetails
1866
+ * / getPatientMedicalDetails actions.
1867
+ */
1868
+ interface PatientDetailsInput {
1869
+ hintId?: string;
1870
+ elationId?: string;
1871
+ }
1872
+ interface PatientDetailsResult {
1873
+ hint: unknown | null;
1874
+ elation: unknown | null;
1875
+ resolvedElationId: string | null;
1876
+ }
1877
+ interface PatientBasicDetailsResult {
1878
+ hint: unknown | null;
1879
+ elationId: string | null;
1880
+ }
1881
+ interface PatientMedicalDetailsResult {
1882
+ problems: unknown | null;
1883
+ medications: unknown | null;
1884
+ allergies: unknown | null;
1885
+ appointments: unknown | null;
1886
+ }
1887
+ declare class PatientDetailsResource {
1888
+ private readonly baseUrl;
1889
+ private readonly apiKey;
1890
+ constructor(apiBaseUrl: string, apiKey: string);
1891
+ private post;
1892
+ get(input: PatientDetailsInput): Promise<PatientDetailsResult>;
1893
+ getBasic(input: PatientDetailsInput): Promise<PatientBasicDetailsResult>;
1894
+ getMedical(elationId: string): Promise<PatientMedicalDetailsResult>;
1895
+ /**
1896
+ * Trigger a server-side refresh of the patient's Elation medical
1897
+ * records (medications, problems, allergies, appointments) into the
1898
+ * Convex cache. Fire-and-forget — the UI should read via the Convex-
1899
+ * reactive `usePatientMedical` hook.
1900
+ */
1901
+ refreshMedical(elationId: number): Promise<{
1902
+ totals: {
1903
+ medications: number;
1904
+ problems: number;
1905
+ allergies: number;
1906
+ appointments: number;
1907
+ };
1908
+ }>;
1909
+ }
1910
+
1911
+ /**
1912
+ * PatientResource provides data access to normalized patient records
1913
+ * backed by Convex.
1914
+ */
1915
+
1916
+ declare class PatientResource {
1917
+ private readonly convex;
1918
+ constructor(convexClient: ConvexHttpClient);
1919
+ /**
1920
+ * Get a patient by their Truth platform ID.
1921
+ */
1922
+ get(id: string): Promise<Patient | null>;
1923
+ /**
1924
+ * Get a patient by their Elation EHR ID.
1925
+ */
1926
+ getByElationId(elationId: string): Promise<Patient | null>;
1927
+ /**
1928
+ * Get a patient by their Hint EHR ID.
1929
+ */
1930
+ getByHintId(hintId: string): Promise<Patient | null>;
1931
+ /**
1932
+ * List patients with optional search, pagination, and limit.
1933
+ */
1934
+ list(options?: PatientListOptions): Promise<PaginatedResult<Patient>>;
2082
1935
  }
2083
1936
 
2084
1937
  /**
2085
- * NotificationsResourcewraps Truth's /api/notifications/* endpoints.
2086
- *
2087
- * Server-side use (for example from a CommHub backend job or
2088
- * another service): `truth.notifications.send({ userId, title, body })`.
1938
+ * PhysiciansResourceConvex-backed physician lookups.
2089
1939
  *
2090
- * Client-side React usage lives in `@hipnation-truth/sdk/react` via
2091
- * the `useNotifications` hook which mirrors `expo-notifications`.
1940
+ * Populated from Elation by Truth's daily PhysiciansBackfillCron. Replaces
1941
+ * per-physician Elation HTTP hops with a single Convex batch query.
2092
1942
  */
2093
- type NotificationPlatform = "ios" | "android" | "web";
2094
- interface RegisterDeviceInput {
2095
- userId: string;
2096
- platform: NotificationPlatform;
2097
- nativeToken?: string;
2098
- webPushSubscription?: {
2099
- endpoint: string;
2100
- keys: {
2101
- p256dh: string;
2102
- auth: string;
2103
- };
2104
- };
2105
- appVersion?: string;
2106
- osVersion?: string;
2107
- locale?: string;
2108
- timezone?: string;
1943
+
1944
+ interface Physician {
1945
+ _id: string;
1946
+ elationId: number;
1947
+ firstName?: string;
1948
+ lastName?: string;
1949
+ npi?: string;
1950
+ credentials?: string;
1951
+ specialties?: string[];
1952
+ practice?: number;
1953
+ email?: string;
1954
+ phone?: string;
1955
+ lastSyncedAt: string;
1956
+ }
1957
+ declare class PhysiciansResource {
1958
+ private readonly convex;
1959
+ constructor(convex: ConvexHttpClient);
2109
1960
  /**
2110
- * iOS only which APNs endpoint the `nativeToken` was issued
2111
- * against. The token bytes don't carry this; it's determined by
2112
- * the build's `aps-environment` entitlement
2113
- * (`development` ⇒ sandbox, `production` ⇒ production). When the
2114
- * consumer is an Expo app, detect via
2115
- * `Application.getIosPushNotificationServiceEnvironmentAsync()`
2116
- * from `expo-application` and pass the normalised value here.
2117
- * Omitting this falls back to the application's default
2118
- * `pushConfig.ios.environment` server-side.
1961
+ * Resolve a batch of physicians by Elation IDs. Missing ids are dropped.
2119
1962
  */
2120
- apnsEnvironment?: "sandbox" | "production";
1963
+ getByElationIds(ids: number[]): Promise<Physician[]>;
1964
+ getByElationId(id: number): Promise<Physician | null>;
1965
+ listByPractice(practice: number, limit?: number): Promise<Physician[]>;
2121
1966
  }
2122
- interface RegisterDeviceResult {
2123
- deviceId: string;
2124
- action: "inserted" | "updated";
2125
- snsEndpointArn?: string;
1967
+
1968
+ /**
1969
+ * Reminder types — scheduled conversation reminders.
1970
+ */
1971
+ type ReminderStatus = "pending" | "triggered" | "cancelled";
1972
+ interface Reminder {
1973
+ _id: string;
1974
+ conversationId: string;
1975
+ remindAt: string;
1976
+ status: ReminderStatus;
1977
+ note?: string;
1978
+ createdBy: string;
1979
+ createdAt: string;
1980
+ triggeredAt?: string;
1981
+ cancelledAt?: string;
2126
1982
  }
2127
- interface UnregisterDeviceInput {
2128
- nativeToken?: string;
2129
- deviceId?: string;
1983
+ interface ScheduleReminderInput {
1984
+ conversationId: string;
1985
+ remindAt: string | Date;
1986
+ note?: string;
1987
+ createdBy: string;
2130
1988
  }
2131
- interface SendNotificationInput {
2132
- userId: string;
2133
- title: string;
2134
- body: string;
2135
- data?: Record<string, unknown>;
2136
- badge?: number;
2137
- sound?: string;
1989
+ interface ScheduleReminderResult {
1990
+ reminderId: string;
1991
+ remindAt: string;
2138
1992
  }
2139
- interface SendNotificationResult {
2140
- delivered: number;
2141
- failed?: number;
2142
- suppressed?: boolean;
2143
- suppressionReason?: string;
1993
+
1994
+ /**
1995
+ * RemindersResource — schedule, cancel, and list conversation reminders.
1996
+ *
1997
+ * Backed by Convex mutations/queries (durable scheduled functions) — replaces
1998
+ * the in-memory setTimeout scheduler that used to live in CommHub's NestJS
1999
+ * backend.
2000
+ */
2001
+
2002
+ declare class RemindersResource {
2003
+ private readonly convex;
2004
+ constructor(convexClient: ConvexHttpClient);
2005
+ /**
2006
+ * Schedule a reminder to fire at `remindAt`. Returns the reminder id,
2007
+ * which callers should store if they may want to cancel it later.
2008
+ */
2009
+ schedule(input: ScheduleReminderInput): Promise<ScheduleReminderResult>;
2010
+ /**
2011
+ * Cancel a pending reminder. No-op if the reminder has already fired or
2012
+ * been cancelled.
2013
+ */
2014
+ cancel(reminderId: string, cancelledBy: string): Promise<{
2015
+ reminderId: string;
2016
+ status: string;
2017
+ }>;
2018
+ /**
2019
+ * List reminders for a conversation (most recent first).
2020
+ */
2021
+ listByConversation(conversationId: string): Promise<Reminder[]>;
2144
2022
  }
2145
- interface NotificationPreferences {
2146
- channels: {
2147
- sms: boolean;
2148
- push: boolean;
2149
- email: boolean;
2150
- inApp: boolean;
2151
- };
2152
- quietHours?: {
2153
- enabled: boolean;
2154
- start: string;
2155
- end: string;
2156
- timezone: string;
2157
- };
2158
- doNotDisturbUntil?: string;
2023
+
2024
+ type TaskStatus = "open" | "in_progress" | "resolved" | "cancelled";
2025
+ interface Task {
2026
+ _id: string;
2027
+ eventId?: string;
2028
+ assignedTo: string;
2029
+ createdBy: string;
2030
+ title: string;
2031
+ description?: string;
2032
+ data?: unknown;
2033
+ status: TaskStatus;
2034
+ resolvedBy?: string;
2035
+ resolvedAt?: string;
2036
+ createdAt: string;
2159
2037
  updatedAt: string;
2160
2038
  }
2161
- interface UpdatePreferencesInput {
2162
- userId: string;
2163
- channels?: NotificationPreferences["channels"];
2164
- quietHours?: NotificationPreferences["quietHours"];
2165
- doNotDisturbUntil?: string | null;
2039
+ interface CreateTaskInput {
2040
+ eventId?: string;
2041
+ assignedTo: string;
2042
+ createdBy: string;
2043
+ title: string;
2044
+ description?: string;
2045
+ data?: unknown;
2166
2046
  }
2167
- interface ScheduleNotificationInput extends SendNotificationInput {
2168
- /** ISO 8601 timestamp; must be strictly in the future. */
2169
- scheduledAt: string;
2047
+ interface UpdateTaskStatusInput {
2048
+ taskId: string;
2049
+ status: TaskStatus;
2050
+ resolvedBy?: string;
2051
+ data?: unknown;
2170
2052
  }
2171
- interface ScheduleNotificationResult {
2172
- jobId: string;
2173
- scheduledAt: string;
2053
+ /**
2054
+ * Input for `tasks.markSeen()` — marks a conversation task as seen by
2055
+ * the given user, backing CommHub's My Tasks "unseen" indicator.
2056
+ */
2057
+ interface ConversationTaskMarkSeenInput {
2058
+ /** Convex `_id` of the `conversationTasks` row. */
2059
+ taskId: string;
2060
+ /** User id of the person who viewed the task. */
2061
+ userId: string;
2174
2062
  }
2175
- interface CancelScheduledNotificationResult {
2176
- cancelled: boolean;
2177
- reason?: string;
2178
- status?: string;
2063
+
2064
+ /**
2065
+ * TasksResource — create, update status, list, get tasks.
2066
+ *
2067
+ * Backed by Convex. Replaces CommHub's createTaskWithNotification +
2068
+ * updateTaskStatusWithNotification actions. Push notification side-effect
2069
+ * is emitted downstream via Kinesis.
2070
+ */
2071
+
2072
+ declare class TasksResource {
2073
+ private readonly convex;
2074
+ constructor(convexClient: ConvexHttpClient);
2075
+ create(input: CreateTaskInput): Promise<{
2076
+ taskId: string;
2077
+ status: TaskStatus;
2078
+ }>;
2079
+ updateStatus(input: UpdateTaskStatusInput): Promise<{
2080
+ taskId: string;
2081
+ status: TaskStatus;
2082
+ previousStatus: TaskStatus;
2083
+ }>;
2084
+ get(taskId: string): Promise<Task | null>;
2085
+ listByAssignee(assignedTo: string, options?: {
2086
+ status?: TaskStatus;
2087
+ limit?: number;
2088
+ }): Promise<Task[]>;
2089
+ listOpen(limit?: number): Promise<Task[]>;
2090
+ /**
2091
+ * Mark a conversation task as seen by the given user. Appends `userId`
2092
+ * to the `seenBy` array on the `conversationTasks` row if not already
2093
+ * present. Replaces CommHub's `useMark_Event_Activity_SeenMutation`.
2094
+ *
2095
+ * @returns `{ ok: true }` on success.
2096
+ * @throws if the task does not exist in Convex.
2097
+ */
2098
+ markSeen(input: ConversationTaskMarkSeenInput): Promise<{
2099
+ ok: true;
2100
+ }>;
2179
2101
  }
2180
- type ScheduledJobStatus = "pending" | "executed" | "cancelled" | "failed";
2181
- interface ScheduledNotification {
2182
- jobId: string;
2183
- userId: string;
2184
- title: string;
2185
- body: string;
2186
- data?: unknown;
2187
- badge?: number;
2188
- sound?: string;
2189
- scheduledAt: string;
2190
- status: ScheduledJobStatus;
2191
- resultHistoryId?: string;
2192
- errorMessage?: string;
2193
- createdAt: string;
2102
+
2103
+ interface TranslationResult {
2104
+ translatedText: string;
2105
+ detectedLanguage?: {
2106
+ language: string;
2107
+ score: number;
2108
+ };
2109
+ sourceLanguage: string;
2110
+ targetLanguage: string;
2194
2111
  }
2195
- interface PushEventPayload {
2196
- title: string;
2197
- body: string;
2198
- data?: unknown;
2112
+ interface DetectionResult {
2113
+ language: string;
2114
+ score: number;
2115
+ isTranslationSupported: boolean;
2116
+ isTransliterationSupported: boolean;
2199
2117
  }
2200
- declare class NotificationsResource {
2118
+ interface TranslateTextInput {
2119
+ text: string;
2120
+ targetLanguage: string;
2121
+ sourceLanguage?: string;
2122
+ }
2123
+ interface TranslateBatchInput {
2124
+ texts: string[];
2125
+ targetLanguage: string;
2126
+ sourceLanguage?: string;
2127
+ }
2128
+
2129
+ /**
2130
+ * TranslationResource — Azure Translator proxy through Truth API.
2131
+ *
2132
+ * All three operations are HTTP calls to Truth's oRPC endpoints at
2133
+ * `/api/translation/*`, authenticated with the same X-API-Key as the
2134
+ * event tracker.
2135
+ */
2136
+
2137
+ declare class TranslationResource {
2201
2138
  private readonly baseUrl;
2202
2139
  private readonly apiKey;
2203
2140
  constructor(apiBaseUrl: string, apiKey: string);
2204
2141
  private post;
2205
- private get;
2206
- private delete;
2207
- /**
2208
- * Register a device (or refresh its metadata) for push delivery.
2209
- * Safe to call repeatedly — the server dedupes by native token.
2210
- */
2211
- registerDevice(input: RegisterDeviceInput): Promise<RegisterDeviceResult>;
2212
- /** Revoke a device — on sign-out or when the OS reports an invalid token. */
2213
- unregisterDevice(input: UnregisterDeviceInput): Promise<{
2214
- revoked: boolean;
2215
- }>;
2216
- /**
2217
- * Send a push notification to every active device belonging to
2218
- * `userId`. Honors the user's notificationPreferences (quiet hours,
2219
- * DND, channel off) before publishing.
2220
- */
2221
- send(input: SendNotificationInput): Promise<SendNotificationResult>;
2222
- /** Read a user's notification preferences. Returns defaults when no row exists. */
2223
- getPreferences(userId: string): Promise<NotificationPreferences>;
2224
- updatePreferences(input: UpdatePreferencesInput): Promise<{
2225
- ok: boolean;
2226
- }>;
2227
- /**
2228
- * Schedule a future push notification. Convex's native scheduler
2229
- * fires the send at `scheduledAt` and runs the same delivery
2230
- * pipeline as `send()` (preferences, devices, history audit).
2231
- *
2232
- * Throws `NotificationsError` with status 400 if `scheduledAt` is
2233
- * not strictly in the future.
2234
- */
2235
- schedule(input: ScheduleNotificationInput): Promise<ScheduleNotificationResult>;
2236
- /**
2237
- * Cancel a pending scheduled notification. Returns `cancelled: false`
2238
- * (no error) if the job has already executed, was previously
2239
- * cancelled, or no longer exists — `reason` describes which case.
2240
- */
2241
- cancelScheduled(jobId: string): Promise<CancelScheduledNotificationResult>;
2142
+ translate(input: TranslateTextInput): Promise<TranslationResult>;
2143
+ translateBatch(input: TranslateBatchInput): Promise<TranslationResult[]>;
2144
+ detect(text: string): Promise<DetectionResult>;
2145
+ }
2146
+
2147
+ /**
2148
+ * UserSettingsResource — typed client for the Truth `userSettings` Convex
2149
+ * table. Exposes the one mutation CommHub's Settings screen needs:
2150
+ * `updateNotifications({ userId, notificationsEnabled })`.
2151
+ *
2152
+ * Server-side / imperative use:
2153
+ * truth.userSettings.updateNotifications({ userId, notificationsEnabled: true })
2154
+ *
2155
+ * Reactive React use lives in `@hipnation-truth/sdk/react` via
2156
+ * `useUserSettings`.
2157
+ */
2158
+
2159
+ interface UserSettings {
2160
+ _id: string;
2161
+ userId: string;
2162
+ notificationsEnabled: boolean;
2163
+ createdAt: string;
2164
+ updatedAt: string;
2165
+ }
2166
+ interface UpdateNotificationsInput {
2167
+ userId: string;
2168
+ notificationsEnabled: boolean;
2169
+ }
2170
+ interface UpdateNotificationsResult {
2171
+ action: "inserted" | "updated";
2172
+ id: string;
2173
+ }
2174
+ declare class UserSettingsResource {
2175
+ private readonly convex;
2176
+ constructor(convex: ConvexHttpClient);
2242
2177
  /**
2243
- * List scheduled notifications for a user pending, executed,
2244
- * cancelled, or failed. Most-recent first. Default limit 100.
2178
+ * Upsert notification preferences for a user. Creates the row if it
2179
+ * doesn't exist; patches `notificationsEnabled` + `updatedAt` otherwise.
2245
2180
  */
2246
- listScheduled(userId: string, options?: {
2247
- limit?: number;
2248
- }): Promise<ScheduledNotification[]>;
2249
- getVapidKey(): Promise<string | null>;
2250
- onPushReceived(callback: (payload: PushEventPayload) => void): () => void;
2251
- onPushTapped(callback: (payload: PushEventPayload) => void): () => void;
2181
+ updateNotifications(input: UpdateNotificationsInput): Promise<UpdateNotificationsResult>;
2252
2182
  }
2253
2183
 
2254
2184
  /**
2255
- * PatientDetailsResource merged Hint + Elation patient lookups.
2185
+ * Typed event definitions for the Truth Platform event store.
2256
2186
  *
2257
- * Backed by the Truth API at /api/patients/details/*, authenticated with
2258
- * X-API-Key. Replaces CommHub's getPatientDetails / getPatientBasicDetails
2259
- * / getPatientMedicalDetails actions.
2187
+ * All 26 event types from the Communication Hub -> Truth Event Store Contract.
2188
+ * Events are grouped by domain and include typed payload interfaces.
2260
2189
  */
2261
- interface PatientDetailsInput {
2262
- hintId?: string;
2263
- elationId?: string;
2190
+ declare const CONVERSATION_EVENTS: {
2191
+ readonly created: "conversation.created.v1";
2192
+ readonly messageSent: "conversation.message_sent.v1";
2193
+ readonly messageReceived: "conversation.message_received.v1";
2194
+ readonly markedRead: "conversation.marked_read.v1";
2195
+ readonly attachmentUploaded: "conversation.attachment_uploaded.v1";
2196
+ readonly attachmentDownloaded: "conversation.attachment_downloaded.v1";
2197
+ };
2198
+ declare const CALL_EVENTS: {
2199
+ readonly initiated: "call.initiated.v1";
2200
+ readonly connected: "call.connected.v1";
2201
+ readonly ended: "call.ended.v1";
2202
+ readonly missed: "call.missed.v1";
2203
+ };
2204
+ declare const TASK_EVENTS: {
2205
+ readonly created: "task.created.v1";
2206
+ readonly assigned: "task.assigned.v1";
2207
+ readonly statusChanged: "task.status_changed.v1";
2208
+ };
2209
+ declare const REMINDER_EVENTS: {
2210
+ readonly scheduled: "reminder.scheduled.v1";
2211
+ readonly triggered: "reminder.triggered.v1";
2212
+ };
2213
+ declare const TRANSLATION_EVENTS: {
2214
+ readonly requested: "translation.requested.v1";
2215
+ readonly completed: "translation.completed.v1";
2216
+ };
2217
+ declare const NOTIFICATION_EVENTS: {
2218
+ readonly sent: "notification.sent.v1";
2219
+ readonly delivered: "notification.delivered.v1";
2220
+ readonly opened: "notification.opened.v1";
2221
+ };
2222
+ declare const PROVIDER_EVENTS: {
2223
+ readonly syncStarted: "provider.sync_started.v1";
2224
+ readonly syncSucceeded: "provider.sync_succeeded.v1";
2225
+ readonly syncFailed: "provider.sync_failed.v1";
2226
+ };
2227
+ declare const AUTH_EVENTS: {
2228
+ readonly loginSucceeded: "auth.login_succeeded.v1";
2229
+ readonly loginFailed: "auth.login_failed.v1";
2230
+ };
2231
+ declare const SECURITY_EVENTS: {
2232
+ readonly accessDenied: "security.access_denied.v1";
2233
+ };
2234
+ type ConversationEventType = (typeof CONVERSATION_EVENTS)[keyof typeof CONVERSATION_EVENTS];
2235
+ type CallEventType = (typeof CALL_EVENTS)[keyof typeof CALL_EVENTS];
2236
+ type TaskEventType = (typeof TASK_EVENTS)[keyof typeof TASK_EVENTS];
2237
+ type ReminderEventType = (typeof REMINDER_EVENTS)[keyof typeof REMINDER_EVENTS];
2238
+ type TranslationEventType = (typeof TRANSLATION_EVENTS)[keyof typeof TRANSLATION_EVENTS];
2239
+ type NotificationEventType = (typeof NOTIFICATION_EVENTS)[keyof typeof NOTIFICATION_EVENTS];
2240
+ type ProviderEventType = (typeof PROVIDER_EVENTS)[keyof typeof PROVIDER_EVENTS];
2241
+ type AuthEventType = (typeof AUTH_EVENTS)[keyof typeof AUTH_EVENTS];
2242
+ type SecurityEventType = (typeof SECURITY_EVENTS)[keyof typeof SECURITY_EVENTS];
2243
+ /**
2244
+ * Union of all 26 registered event type strings.
2245
+ */
2246
+ type EventType = ConversationEventType | CallEventType | TaskEventType | ReminderEventType | TranslationEventType | NotificationEventType | ProviderEventType | AuthEventType | SecurityEventType;
2247
+ interface ConversationCreatedPayload {
2248
+ channel: string;
2249
+ origin_system: string;
2250
+ participant_count: number;
2264
2251
  }
2265
- interface PatientDetailsResult {
2266
- hint: unknown | null;
2267
- elation: unknown | null;
2268
- resolvedElationId: string | null;
2252
+ interface ConversationMessageSentPayload {
2253
+ channel: string;
2254
+ direction: string;
2255
+ message_chars: number;
2256
+ has_attachment: boolean;
2257
+ provider_system: string;
2269
2258
  }
2270
- interface PatientBasicDetailsResult {
2271
- hint: unknown | null;
2272
- elationId: string | null;
2259
+ interface ConversationMessageReceivedPayload {
2260
+ channel: string;
2261
+ direction: string;
2262
+ message_chars: number;
2263
+ provider_system: string;
2264
+ }
2265
+ interface ConversationMarkedReadPayload {
2266
+ read_by_actor_id: string;
2267
+ unread_count_before: number;
2268
+ unread_count_after: number;
2269
+ }
2270
+ interface ConversationAttachmentUploadedPayload {
2271
+ attachment_id: string;
2272
+ mime_type: string;
2273
+ size_bytes: number;
2274
+ storage_class: string;
2275
+ }
2276
+ interface ConversationAttachmentDownloadedPayload {
2277
+ attachment_id: string;
2278
+ download_actor_type: string;
2279
+ access_path: string;
2280
+ }
2281
+ interface CallInitiatedPayload {
2282
+ direction: string;
2283
+ provider_system: string;
2284
+ from_number_ref: string;
2285
+ to_number_ref: string;
2286
+ }
2287
+ interface CallConnectedPayload {
2288
+ provider_system: string;
2289
+ ring_duration_ms: number;
2290
+ }
2291
+ interface CallEndedPayload {
2292
+ provider_system: string;
2293
+ duration_ms: number;
2294
+ end_reason: string;
2295
+ disposition: string;
2296
+ }
2297
+ interface CallMissedPayload {
2298
+ provider_system: string;
2299
+ miss_reason: string;
2300
+ }
2301
+ interface TaskCreatedPayload {
2302
+ task_id: string;
2303
+ created_by: string;
2304
+ assigned_to: string;
2305
+ priority: string;
2306
+ due_at: string;
2307
+ }
2308
+ interface TaskAssignedPayload {
2309
+ task_id: string;
2310
+ assigned_to: string;
2311
+ assigned_by: string;
2312
+ }
2313
+ interface TaskStatusChangedPayload {
2314
+ task_id: string;
2315
+ status_from: string;
2316
+ status_to: string;
2317
+ changed_by: string;
2273
2318
  }
2274
- interface PatientMedicalDetailsResult {
2275
- problems: unknown | null;
2276
- medications: unknown | null;
2277
- allergies: unknown | null;
2278
- appointments: unknown | null;
2319
+ interface ReminderScheduledPayload {
2320
+ reminder_id: string;
2321
+ conversation_id: string;
2322
+ scheduled_for: string;
2323
+ scheduled_by: string;
2279
2324
  }
2280
- declare class PatientDetailsResource {
2281
- private readonly baseUrl;
2282
- private readonly apiKey;
2283
- constructor(apiBaseUrl: string, apiKey: string);
2284
- private post;
2285
- get(input: PatientDetailsInput): Promise<PatientDetailsResult>;
2286
- getBasic(input: PatientDetailsInput): Promise<PatientBasicDetailsResult>;
2287
- getMedical(elationId: string): Promise<PatientMedicalDetailsResult>;
2288
- /**
2289
- * Trigger a server-side refresh of the patient's Elation medical
2290
- * records (medications, problems, allergies, appointments) into the
2291
- * Convex cache. Fire-and-forget — the UI should read via the Convex-
2292
- * reactive `usePatientMedical` hook.
2293
- */
2294
- refreshMedical(elationId: number): Promise<{
2295
- totals: {
2296
- medications: number;
2297
- problems: number;
2298
- allergies: number;
2299
- appointments: number;
2300
- };
2301
- }>;
2325
+ interface ReminderTriggeredPayload {
2326
+ reminder_id: string;
2327
+ trigger_result: string;
2328
+ notification_attempted: boolean;
2302
2329
  }
2303
-
2304
- /**
2305
- * PatientResource provides data access to normalized patient records
2306
- * backed by Convex.
2307
- */
2308
-
2309
- declare class PatientResource {
2310
- private readonly convex;
2311
- constructor(convexClient: ConvexHttpClient);
2312
- /**
2313
- * Get a patient by their Truth platform ID.
2314
- */
2315
- get(id: string): Promise<Patient | null>;
2316
- /**
2317
- * Get a patient by their Elation EHR ID.
2318
- */
2319
- getByElationId(elationId: string): Promise<Patient | null>;
2320
- /**
2321
- * Get a patient by their Hint EHR ID.
2322
- */
2323
- getByHintId(hintId: string): Promise<Patient | null>;
2324
- /**
2325
- * List patients with optional search, pagination, and limit.
2326
- */
2327
- list(options?: PatientListOptions): Promise<PaginatedResult<Patient>>;
2330
+ interface TranslationRequestedPayload {
2331
+ target_language: string;
2332
+ source_language: string;
2333
+ char_count: number;
2334
+ mode: string;
2328
2335
  }
2329
-
2330
- /**
2331
- * PhysiciansResource — Convex-backed physician lookups.
2332
- *
2333
- * Populated from Elation by Truth's daily PhysiciansBackfillCron. Replaces
2334
- * per-physician Elation HTTP hops with a single Convex batch query.
2335
- */
2336
-
2337
- interface Physician {
2338
- _id: string;
2339
- elationId: number;
2340
- firstName?: string;
2341
- lastName?: string;
2342
- npi?: string;
2343
- credentials?: string;
2344
- specialties?: string[];
2345
- practice?: number;
2346
- email?: string;
2347
- phone?: string;
2348
- lastSyncedAt: string;
2336
+ interface TranslationCompletedPayload {
2337
+ target_language: string;
2338
+ provider: string;
2339
+ latency_ms: number;
2340
+ success: boolean;
2341
+ error_code?: string;
2349
2342
  }
2350
- declare class PhysiciansResource {
2351
- private readonly convex;
2352
- constructor(convex: ConvexHttpClient);
2353
- /**
2354
- * Resolve a batch of physicians by Elation IDs. Missing ids are dropped.
2355
- */
2356
- getByElationIds(ids: number[]): Promise<Physician[]>;
2357
- getByElationId(id: number): Promise<Physician | null>;
2358
- listByPractice(practice: number, limit?: number): Promise<Physician[]>;
2343
+ interface NotificationSentPayload {
2344
+ notification_id: string;
2345
+ channel: string;
2346
+ platform: string;
2347
+ recipient_ref: string;
2348
+ success: boolean;
2359
2349
  }
2360
-
2361
- /**
2362
- * RemindersResource — schedule, cancel, and list conversation reminders.
2363
- *
2364
- * Backed by Convex mutations/queries (durable scheduled functions) — replaces
2365
- * the in-memory setTimeout scheduler that used to live in CommHub's NestJS
2366
- * backend.
2367
- */
2368
-
2369
- declare class RemindersResource {
2370
- private readonly convex;
2371
- constructor(convexClient: ConvexHttpClient);
2372
- /**
2373
- * Schedule a reminder to fire at `remindAt`. Returns the reminder id,
2374
- * which callers should store if they may want to cancel it later.
2375
- */
2376
- schedule(input: ScheduleReminderInput): Promise<ScheduleReminderResult>;
2377
- /**
2378
- * Cancel a pending reminder. No-op if the reminder has already fired or
2379
- * been cancelled.
2380
- */
2381
- cancel(reminderId: string, cancelledBy: string): Promise<{
2382
- reminderId: string;
2383
- status: string;
2384
- }>;
2385
- /**
2386
- * List reminders for a conversation (most recent first).
2387
- */
2388
- listByConversation(conversationId: string): Promise<Reminder[]>;
2350
+ interface NotificationDeliveredPayload {
2351
+ notification_id: string;
2352
+ platform: string;
2353
+ delivered_at: string;
2389
2354
  }
2390
-
2391
- type TaskStatus = "open" | "in_progress" | "resolved" | "cancelled";
2392
- interface Task {
2393
- _id: string;
2394
- eventId?: string;
2395
- assignedTo: string;
2396
- createdBy: string;
2397
- title: string;
2398
- description?: string;
2399
- data?: unknown;
2400
- status: TaskStatus;
2401
- resolvedBy?: string;
2402
- resolvedAt?: string;
2403
- createdAt: string;
2404
- updatedAt: string;
2355
+ interface NotificationOpenedPayload {
2356
+ notification_id: string;
2357
+ platform: string;
2358
+ opened_at: string;
2405
2359
  }
2406
- interface CreateTaskInput {
2407
- eventId?: string;
2408
- assignedTo: string;
2409
- createdBy: string;
2410
- title: string;
2411
- description?: string;
2412
- data?: unknown;
2360
+ interface ProviderSyncStartedPayload {
2361
+ provider_system: string;
2362
+ operation: string;
2363
+ scope: string;
2364
+ batch_id: string;
2413
2365
  }
2414
- interface UpdateTaskStatusInput {
2415
- taskId: string;
2416
- status: TaskStatus;
2417
- resolvedBy?: string;
2418
- data?: unknown;
2366
+ interface ProviderSyncSucceededPayload {
2367
+ provider_system: string;
2368
+ operation: string;
2369
+ batch_id: string;
2370
+ records_processed: number;
2371
+ duration_ms: number;
2419
2372
  }
2420
- /**
2421
- * Input for `tasks.markSeen()` — marks a conversation task as seen by
2422
- * the given user, backing CommHub's My Tasks "unseen" indicator.
2423
- */
2424
- interface ConversationTaskMarkSeenInput {
2425
- /** Convex `_id` of the `conversationTasks` row. */
2426
- taskId: string;
2427
- /** User id of the person who viewed the task. */
2428
- userId: string;
2373
+ interface ProviderSyncFailedPayload {
2374
+ provider_system: string;
2375
+ operation: string;
2376
+ batch_id: string;
2377
+ error_code: string;
2378
+ retryable: boolean;
2429
2379
  }
2430
-
2431
- /**
2432
- * TasksResource — create, update status, list, get tasks.
2433
- *
2434
- * Backed by Convex. Replaces CommHub's createTaskWithNotification +
2435
- * updateTaskStatusWithNotification actions. Push notification side-effect
2436
- * is emitted downstream via Kinesis.
2437
- */
2438
-
2439
- declare class TasksResource {
2440
- private readonly convex;
2441
- constructor(convexClient: ConvexHttpClient);
2442
- create(input: CreateTaskInput): Promise<{
2443
- taskId: string;
2444
- status: TaskStatus;
2445
- }>;
2446
- updateStatus(input: UpdateTaskStatusInput): Promise<{
2447
- taskId: string;
2448
- status: TaskStatus;
2449
- previousStatus: TaskStatus;
2450
- }>;
2451
- get(taskId: string): Promise<Task | null>;
2452
- listByAssignee(assignedTo: string, options?: {
2453
- status?: TaskStatus;
2454
- limit?: number;
2455
- }): Promise<Task[]>;
2456
- listOpen(limit?: number): Promise<Task[]>;
2457
- /**
2458
- * Mark a conversation task as seen by the given user. Appends `userId`
2459
- * to the `seenBy` array on the `conversationTasks` row if not already
2460
- * present. Replaces CommHub's `useMark_Event_Activity_SeenMutation`.
2461
- *
2462
- * @returns `{ ok: true }` on success.
2463
- * @throws if the task does not exist in Convex.
2464
- */
2465
- markSeen(input: ConversationTaskMarkSeenInput): Promise<{
2466
- ok: true;
2467
- }>;
2380
+ interface AuthLoginSucceededPayload {
2381
+ auth_provider: string;
2382
+ platform: string;
2383
+ session_ref: string;
2468
2384
  }
2469
-
2470
- interface TranslationResult {
2471
- translatedText: string;
2472
- detectedLanguage?: {
2473
- language: string;
2474
- score: number;
2475
- };
2476
- sourceLanguage: string;
2477
- targetLanguage: string;
2385
+ interface AuthLoginFailedPayload {
2386
+ auth_provider: string;
2387
+ platform: string;
2388
+ failure_code: string;
2389
+ }
2390
+ interface SecurityAccessDeniedPayload {
2391
+ resource: string;
2392
+ policy: string;
2393
+ reason_code: string;
2394
+ actor_id: string;
2478
2395
  }
2479
- interface DetectionResult {
2480
- language: string;
2481
- score: number;
2482
- isTranslationSupported: boolean;
2483
- isTransliterationSupported: boolean;
2396
+ /**
2397
+ * Maps each event type string to its required payload interface.
2398
+ */
2399
+ interface EventPayloadMap {
2400
+ "conversation.created.v1": ConversationCreatedPayload;
2401
+ "conversation.message_sent.v1": ConversationMessageSentPayload;
2402
+ "conversation.message_received.v1": ConversationMessageReceivedPayload;
2403
+ "conversation.marked_read.v1": ConversationMarkedReadPayload;
2404
+ "conversation.attachment_uploaded.v1": ConversationAttachmentUploadedPayload;
2405
+ "conversation.attachment_downloaded.v1": ConversationAttachmentDownloadedPayload;
2406
+ "call.initiated.v1": CallInitiatedPayload;
2407
+ "call.connected.v1": CallConnectedPayload;
2408
+ "call.ended.v1": CallEndedPayload;
2409
+ "call.missed.v1": CallMissedPayload;
2410
+ "task.created.v1": TaskCreatedPayload;
2411
+ "task.assigned.v1": TaskAssignedPayload;
2412
+ "task.status_changed.v1": TaskStatusChangedPayload;
2413
+ "reminder.scheduled.v1": ReminderScheduledPayload;
2414
+ "reminder.triggered.v1": ReminderTriggeredPayload;
2415
+ "translation.requested.v1": TranslationRequestedPayload;
2416
+ "translation.completed.v1": TranslationCompletedPayload;
2417
+ "notification.sent.v1": NotificationSentPayload;
2418
+ "notification.delivered.v1": NotificationDeliveredPayload;
2419
+ "notification.opened.v1": NotificationOpenedPayload;
2420
+ "provider.sync_started.v1": ProviderSyncStartedPayload;
2421
+ "provider.sync_succeeded.v1": ProviderSyncSucceededPayload;
2422
+ "provider.sync_failed.v1": ProviderSyncFailedPayload;
2423
+ "auth.login_succeeded.v1": AuthLoginSucceededPayload;
2424
+ "auth.login_failed.v1": AuthLoginFailedPayload;
2425
+ "security.access_denied.v1": SecurityAccessDeniedPayload;
2484
2426
  }
2485
- interface TranslateTextInput {
2486
- text: string;
2487
- targetLanguage: string;
2488
- sourceLanguage?: string;
2427
+ /**
2428
+ * Subject references for the event. Uses tokenized references only -- no PHI.
2429
+ */
2430
+ interface EventSubject {
2431
+ patient_ref?: string;
2432
+ conversation_id?: string;
2433
+ task_id?: string;
2434
+ call_id?: string;
2489
2435
  }
2490
- interface TranslateBatchInput {
2491
- texts: string[];
2492
- targetLanguage: string;
2493
- sourceLanguage?: string;
2436
+ /**
2437
+ * Actor who triggered the event.
2438
+ */
2439
+ interface EventActor {
2440
+ actor_id: string;
2441
+ actor_type: "user" | "system" | "webhook";
2494
2442
  }
2495
-
2496
2443
  /**
2497
- * TranslationResource Azure Translator proxy through Truth API.
2498
- *
2499
- * All three operations are HTTP calls to Truth's oRPC endpoints at
2500
- * `/api/translation/*`, authenticated with the same X-API-Key as the
2501
- * event tracker.
2444
+ * Compliance metadata for the event.
2502
2445
  */
2503
-
2504
- declare class TranslationResource {
2505
- private readonly baseUrl;
2506
- private readonly apiKey;
2507
- constructor(apiBaseUrl: string, apiKey: string);
2508
- private post;
2509
- translate(input: TranslateTextInput): Promise<TranslationResult>;
2510
- translateBatch(input: TranslateBatchInput): Promise<TranslationResult[]>;
2511
- detect(text: string): Promise<DetectionResult>;
2446
+ interface EventCompliance {
2447
+ pii_level: "none" | "limited" | "full";
2448
+ contains_phi: boolean;
2449
+ consent_context: string;
2450
+ retention_class: string;
2451
+ }
2452
+ /**
2453
+ * Optional overrides when calling truth.track().
2454
+ */
2455
+ interface TrackOptions {
2456
+ /** Override the default actor for this event */
2457
+ actor?: EventActor;
2458
+ /** Subject references for this event */
2459
+ subject?: EventSubject;
2460
+ /** Compliance metadata for this event */
2461
+ compliance?: EventCompliance;
2462
+ /** Override the default tenant ID for this event */
2463
+ tenantId?: string;
2464
+ /** Override the occurred_at timestamp (ISO 8601) */
2465
+ occurredAt?: string;
2512
2466
  }
2513
2467
 
2514
2468
  /**
@@ -2619,6 +2573,225 @@ declare class TruthClient {
2619
2573
  destroy(): Promise<void>;
2620
2574
  }
2621
2575
 
2576
+ declare const CONVEX_URLS: Record<string, string>;
2577
+ declare const API_BASE_URLS: Record<string, string>;
2578
+ /**
2579
+ * Resolve the Convex URL for a given environment. Honors an explicit
2580
+ * override and falls back to sandbox for unknown environments.
2581
+ */
2582
+ declare function resolveConvexUrl(environment: string | undefined, override?: string): string;
2583
+ /**
2584
+ * Resolve the Truth REST API base URL for a given environment. Mirrors
2585
+ * `resolveConvexUrl`. Honors an explicit override and falls back to
2586
+ * sandbox for unknown environments.
2587
+ */
2588
+ declare function resolveApiBaseUrl(environment: string | undefined, override?: string): string;
2589
+ interface TruthSdkContextValue {
2590
+ apiBaseUrl: string;
2591
+ apiKey: string;
2592
+ environment: string;
2593
+ client: TruthClient;
2594
+ }
2595
+ /**
2596
+ * Read the Truth REST API base URL + API key + shared client from
2597
+ * `TruthProvider`. Returns `null` when the provider isn't mounted,
2598
+ * which lets hooks fall back to explicit options for backwards
2599
+ * compatibility.
2600
+ */
2601
+ declare function useTruthSdkContext(): TruthSdkContextValue | null;
2602
+ /**
2603
+ * Hook variant of `getTruthClient()` for code that lives inside the
2604
+ * React tree. Returns the shared `TruthClient` instance from
2605
+ * `TruthProvider`. Throws if the provider isn't mounted.
2606
+ */
2607
+ declare function useTruthClient(): TruthClient;
2608
+ /**
2609
+ * Return the shared `TruthClient` instance set by `<TruthProvider>`.
2610
+ * Throws if `TruthProvider` hasn't mounted yet — call this only from
2611
+ * code that runs after the provider has rendered (event handlers,
2612
+ * effects, async helpers invoked from rendered components).
2613
+ */
2614
+ declare function getTruthClient(): TruthClient;
2615
+ interface TruthProviderProps {
2616
+ /** Truth environment — determines which Convex + Lambda deployment to use */
2617
+ environment?: string;
2618
+ /** Override the Convex URL directly */
2619
+ convexUrl?: string;
2620
+ /**
2621
+ * Override the Truth REST API base URL directly. Optional — defaults
2622
+ * to the environment-mapped URL (`API_BASE_URLS[environment]`), then
2623
+ * falls back to `process.env.EXPO_PUBLIC_TRUTH_API_BASE_URL` if set.
2624
+ */
2625
+ apiBaseUrl?: string;
2626
+ /**
2627
+ * `hn_live_*` API key for the caller's application. Optional —
2628
+ * defaults to `process.env.EXPO_PUBLIC_TRUTH_API_KEY`. Stored in
2629
+ * React context + on the shared TruthClient, never logged.
2630
+ */
2631
+ apiKey?: string;
2632
+ /**
2633
+ * Optional source / tenant metadata for event tracking. Mirrors
2634
+ * `TruthClient` constructor options.
2635
+ */
2636
+ source?: string;
2637
+ sourceVersion?: string;
2638
+ tenantId?: string;
2639
+ children: ReactNode;
2640
+ }
2641
+ declare function TruthProvider({ environment, convexUrl, apiBaseUrl, apiKey, source, sourceVersion, tenantId, children, }: TruthProviderProps): react.FunctionComponentElement<react.ProviderProps<TruthSdkContextValue | null>>;
2642
+
2643
+ /**
2644
+ * React hooks for conversation reminders — bulk lookup keyed by
2645
+ * conversation id. Wraps the public `reminders:listPendingByConversationIds`
2646
+ * Convex query so CommHub's inbox can render the reminder clock icon
2647
+ * with one reactive subscription for the entire visible list.
2648
+ *
2649
+ * Must be used within `<TruthProvider />` (see `./provider`).
2650
+ */
2651
+
2652
+ /**
2653
+ * Subscribe to the latest pending reminder for each of the given
2654
+ * conversation ids. Returns a `Record<conversationId, Reminder>` —
2655
+ * conversations with no pending reminder are absent from the map.
2656
+ *
2657
+ * Pass an empty array (or `undefined`) to skip the query — useful while
2658
+ * the inbox list is still loading.
2659
+ *
2660
+ * @example
2661
+ * ```tsx
2662
+ * const ids = conversations.map((c) => c.id);
2663
+ * const { data: remindersByConv } = useRemindersForConversations(ids);
2664
+ * const r = remindersByConv?.[conv.id]; // Reminder | undefined
2665
+ * ```
2666
+ */
2667
+ declare function useRemindersForConversations(conversationIds: string[] | null | undefined): UseQueryResult<Record<string, Reminder>>;
2668
+
2669
+ /**
2670
+ * React hooks for conversation tasks (My Tasks surface).
2671
+ *
2672
+ * Provides a reactive `useMutation` wrapper around the
2673
+ * `conversationTasks:markSeen` Convex mutation so CommHub can replace
2674
+ * `useMark_Event_Activity_SeenMutation` from `@/generated/graphql`
2675
+ * with a Truth SDK equivalent without touching `react.ts` exports (the
2676
+ * central agent wires those).
2677
+ *
2678
+ * Pattern mirrors the existing hooks in `./conversations.ts`:
2679
+ * - `makeFunctionReference` for decoupled Convex references
2680
+ * - SKIP sentinel for conditional execution
2681
+ * - Returns a stable callback, not a live subscription
2682
+ *
2683
+ * Must be used within `<TruthProvider />`.
2684
+ */
2685
+ /**
2686
+ * Returns a stable `markSeen(taskId, userId)` callback backed by the
2687
+ * `conversationTasks:markSeen` Convex mutation. Replaces the Hasura
2688
+ * `useMark_Event_Activity_SeenMutation` in CommHub's My Tasks surface.
2689
+ *
2690
+ * @example
2691
+ * ```tsx
2692
+ * const markSeen = useConversationTaskMarkSeen();
2693
+ *
2694
+ * // When a task row is pressed:
2695
+ * if (!task.seenBy.includes(userId)) {
2696
+ * markSeen(task.id, userId).catch(console.error);
2697
+ * }
2698
+ * ```
2699
+ */
2700
+ declare function useConversationTaskMarkSeen(): (taskId: string, userId: string) => Promise<{
2701
+ ok: true;
2702
+ }>;
2703
+
2704
+ interface TruthTrackingContextValue {
2705
+ track: <T extends EventType>(eventType: T, payload: EventPayloadMap[T], options?: TrackOptions) => void;
2706
+ identify: (actorId: string, actorType: ActorContext["actorType"]) => void;
2707
+ }
2708
+ interface TruthTrackingProviderProps {
2709
+ /** Truth environment — determines API URL for event delivery */
2710
+ environment?: string;
2711
+ /** Event source identifier */
2712
+ source?: string;
2713
+ /** Source version (git SHA) */
2714
+ sourceVersion?: string;
2715
+ /** Default tenant ID */
2716
+ tenantId?: string;
2717
+ /** API key for authentication */
2718
+ apiKey?: string;
2719
+ children: ReactNode;
2720
+ }
2721
+ declare function TruthTrackingProvider({ environment, source, sourceVersion, tenantId, apiKey, children, }: TruthTrackingProviderProps): react.FunctionComponentElement<react.ProviderProps<TruthTrackingContextValue | null>>;
2722
+ /**
2723
+ * Access the Truth tracking context. Must be within a TruthTrackingProvider.
2724
+ * Returns `{ track, identify }` for emitting events to Kinesis.
2725
+ */
2726
+ declare function useTruth(): TruthTrackingContextValue;
2727
+
2728
+ /**
2729
+ * useUserSettings — reactive hook for per-user notification preferences
2730
+ * stored in the Truth `userSettings` Convex table.
2731
+ *
2732
+ * Must be used within `<TruthProvider />` (see `./provider`).
2733
+ *
2734
+ * @example
2735
+ * ```tsx
2736
+ * const { data: settings, loading } = useUserSettings(userId);
2737
+ * // settings?.notificationsEnabled — boolean or undefined (no row yet)
2738
+ * ```
2739
+ */
2740
+
2741
+ /**
2742
+ * Subscribe to the `userSettings` row for `userId`. Returns `null` when
2743
+ * no row exists (treat as all-defaults). Returns `undefined` while the
2744
+ * Convex query is in-flight.
2745
+ *
2746
+ * Pass `null` or `undefined` as `userId` to skip the query (e.g. while
2747
+ * auth is loading).
2748
+ */
2749
+ declare function useUserSettings(userId: string | null | undefined): UseQueryResult<UserSettings | null>;
2750
+
2751
+ /**
2752
+ * useUserSync — mirror the caller's Clerk profile into Truth's user roster.
2753
+ *
2754
+ * Truth's `users` Convex table backs the SMS push fan-out (office cohort
2755
+ * + `notifications_enabled`), assignee pickers, and office-scoped
2756
+ * filters. CommHub mounts this hook on app start so the active user
2757
+ * lands in Truth without anyone reaching into Hasura.
2758
+ *
2759
+ * Resolves `apiBaseUrl` + `apiKey` from `<TruthProvider>` context, so
2760
+ * the call site only passes the per-user details:
2761
+ *
2762
+ * ```tsx
2763
+ * useUserSync({ userId, email, name, imageUrl });
2764
+ * ```
2765
+ *
2766
+ * Idempotent — fires once per (userId, email, name, imageUrl) change.
2767
+ */
2768
+ interface UseUserSyncInput {
2769
+ /** Truth API base URL. Defaults to TruthProvider context. */
2770
+ apiBaseUrl?: string;
2771
+ /** `hn_live_*` application key. Defaults to TruthProvider context. */
2772
+ apiKey?: string;
2773
+ /** Clerk userId. The hook is a no-op while this is nullish. */
2774
+ userId: string | null | undefined;
2775
+ email?: string;
2776
+ name?: string;
2777
+ firstName?: string;
2778
+ lastName?: string;
2779
+ imageUrl?: string;
2780
+ notificationsEnabled?: boolean;
2781
+ }
2782
+ interface UseUserSyncResult {
2783
+ /** "idle" before any sync, "syncing" mid-fetch, "synced" on success, "error" otherwise. */
2784
+ status: "idle" | "syncing" | "synced" | "error";
2785
+ /** Last error message when status === "error". */
2786
+ error: string | null;
2787
+ /** Manually re-run the sync. Usually not needed — the hook auto-syncs. */
2788
+ sync: () => Promise<{
2789
+ ok: boolean;
2790
+ reason?: string;
2791
+ }>;
2792
+ }
2793
+ declare function useUserSync(input: UseUserSyncInput): UseUserSyncResult;
2794
+
2622
2795
  /**
2623
2796
  * React hook for fetching an authenticated Dialpad voicemail URL.
2624
2797
  *
@@ -2664,4 +2837,4 @@ interface UseVoicemailUrlResult {
2664
2837
  */
2665
2838
  declare function useVoicemailUrl(client: TruthClient): UseVoicemailUrlResult;
2666
2839
 
2667
- export { ACTIVE_CALL_STATES, type Appointment, type AppointmentListOptions, CONNECTED_CALL_STATES, type ConversationListItem, type ConversationMessage, type ConversationMessageRow, type ConversationNoteRow, type ConversationRow, type ConversationTaskForUserRow, type ConversationTaskRow, type DialpadCallLogRow, type DialpadCallRow, DialpadCallState, type EventPayloadMap, type EventType, type FamilyMemberRow, type Patient, type PatientListOptions, type PatientSearchResult, type PermissionStatus, type Physician$1 as Physician, RINGING_CALL_STATES, TERMINAL_CALL_STATES, type TrackOptions, TruthProvider, type TruthProviderProps, type TruthTrackingContextValue, TruthTrackingProvider, type TruthTrackingProviderProps, type UseActiveCallsOptions, type UseAppointmentListOptions, type UseConversationMessagesOptions, type UseConversationsFilters, type UseMessagesOptions, type UseNotificationsOptions, type UseNotificationsResult, type UsePatientBasicOptions, type UsePatientBasicResult, type UsePatientFamilyMembersInput, type UsePatientListOptions, type UsePatientMedicalOptions, type UsePatientPhotoOptions, type UsePatientSearchOptions, type UseQueryResult, useActiveCalls, useAppointment, useAppointmentByElationId, useAppointments, useConversationById, useConversationByPhonePair, useConversationMessages, useConversationNotes, useConversationNotesByPhonePair, useConversationTaskMarkSeen, useConversationTasks, useConversationTasksByPhonePair, useConversationTasksForUser, useConversations, useDialpadCallByCallId, useDialpadCallLog, useDialpadCallsForConversation, useMessages, useNotifications, usePatient, usePatientBasic, usePatientByElationId, usePatientByHintId, usePatientFamilyMembers, usePatientMedical, usePatientPhoto, usePatientSearch, usePatients, usePatientsByIds, usePatientsByPhones, usePharmacyByNcpdpId, usePhysicianByElationId, usePhysiciansByElationIds, useRemindersForConversations, useTruth, useUnreadAggregate, useUnreadCount, useUserSettings, useVoicemailUrl };
2840
+ export { ACTIVE_CALL_STATES, API_BASE_URLS, type Appointment, type AppointmentListOptions, CONNECTED_CALL_STATES, CONVEX_URLS, type ConversationListItem, type ConversationMessage, type ConversationMessageRow, type ConversationNoteRow, type ConversationRow, type ConversationTaskForUserRow, type ConversationTaskRow, type DialpadCallLogRow, type DialpadCallRow, DialpadCallState, type EventPayloadMap, type EventType, type FamilyMemberRow, type Patient, type PatientListOptions, type PatientSearchResult, type PermissionStatus, type Physician$1 as Physician, RINGING_CALL_STATES, TERMINAL_CALL_STATES, type TrackOptions, TruthProvider, type TruthProviderProps, type TruthTrackingContextValue, TruthTrackingProvider, type TruthTrackingProviderProps, type UseActiveCallsOptions, type UseAppointmentListOptions, type UseConversationMessagesOptions, type UseConversationsFilters, type UseMessagesOptions, type UseNotificationsActions, type UseNotificationsOptions, type UseNotificationsResult, type UsePatientBasicOptions, type UsePatientBasicResult, type UsePatientFamilyMembersInput, type UsePatientListOptions, type UsePatientMedicalOptions, type UsePatientPhotoOptions, type UsePatientSearchOptions, type UseQueryResult, type UseUserSyncInput, type UseUserSyncResult, getTruthClient, resolveApiBaseUrl, resolveConvexUrl, useActiveCalls, useAppointment, useAppointmentByElationId, useAppointments, useConversationById, useConversationByPhonePair, useConversationMessages, useConversationNotes, useConversationNotesByPhonePair, useConversationTaskMarkSeen, useConversationTasks, useConversationTasksByPhonePair, useConversationTasksForUser, useConversations, useDialpadCallByCallId, useDialpadCallLog, useDialpadCallsForConversation, useMessages, useNotifications, useNotificationsActions, usePatient, usePatientBasic, usePatientByElationId, usePatientByHintId, usePatientFamilyMembers, usePatientMedical, usePatientPhoto, usePatientSearch, usePatients, usePatientsByIds, usePatientsByPhones, usePharmacyByNcpdpId, usePhysicianByElationId, usePhysiciansByElationIds, useRemindersForConversations, useTruth, useTruthClient, useTruthSdkContext, useUnreadAggregate, useUnreadCount, useUserSettings, useUserSync, useVoicemailUrl };