@tellescope/sdk 1.256.11 → 1.256.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/lib/cjs/sdk.d.ts +1 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/sdk.js +1 -0
  4. package/lib/cjs/sdk.js.map +1 -1
  5. package/lib/cjs/tests/api_tests/active_patient_count.test.d.ts +15 -0
  6. package/lib/cjs/tests/api_tests/active_patient_count.test.d.ts.map +1 -0
  7. package/lib/cjs/tests/api_tests/active_patient_count.test.js +594 -0
  8. package/lib/cjs/tests/api_tests/active_patient_count.test.js.map +1 -0
  9. package/lib/cjs/tests/api_tests/out_of_office_endpoint.test.d.ts +6 -0
  10. package/lib/cjs/tests/api_tests/out_of_office_endpoint.test.d.ts.map +1 -0
  11. package/lib/cjs/tests/api_tests/out_of_office_endpoint.test.js +192 -0
  12. package/lib/cjs/tests/api_tests/out_of_office_endpoint.test.js.map +1 -0
  13. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts +5 -0
  14. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts.map +1 -1
  15. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +95 -31
  16. package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
  17. package/lib/cjs/tests/tests.d.ts.map +1 -1
  18. package/lib/cjs/tests/tests.js +156 -148
  19. package/lib/cjs/tests/tests.js.map +1 -1
  20. package/lib/esm/sdk.d.ts +1 -0
  21. package/lib/esm/sdk.d.ts.map +1 -1
  22. package/lib/esm/sdk.js +1 -0
  23. package/lib/esm/sdk.js.map +1 -1
  24. package/lib/esm/tests/api_tests/active_patient_count.test.d.ts +15 -0
  25. package/lib/esm/tests/api_tests/active_patient_count.test.d.ts.map +1 -0
  26. package/lib/esm/tests/api_tests/active_patient_count.test.js +590 -0
  27. package/lib/esm/tests/api_tests/active_patient_count.test.js.map +1 -0
  28. package/lib/esm/tests/api_tests/out_of_office_endpoint.test.d.ts +6 -0
  29. package/lib/esm/tests/api_tests/out_of_office_endpoint.test.d.ts.map +1 -0
  30. package/lib/esm/tests/api_tests/out_of_office_endpoint.test.js +188 -0
  31. package/lib/esm/tests/api_tests/out_of_office_endpoint.test.js.map +1 -0
  32. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts +5 -0
  33. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts.map +1 -1
  34. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +95 -31
  35. package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -1
  36. package/lib/esm/tests/tests.d.ts.map +1 -1
  37. package/lib/esm/tests/tests.js +156 -148
  38. package/lib/esm/tests/tests.js.map +1 -1
  39. package/lib/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +10 -10
  41. package/src/sdk.ts +4 -0
  42. package/src/tests/api_tests/active_patient_count.test.ts +435 -0
  43. package/src/tests/api_tests/out_of_office_endpoint.test.ts +162 -0
  44. package/src/tests/api_tests/security/enduser-ai-summary-trust-gate.test.ts +56 -0
  45. package/src/tests/tests.ts +4 -0
  46. package/test_generated.pdf +0 -0
@@ -12,6 +12,7 @@ const ENDUSER_PASSWORD = 'AISummaryGateTestPassword!123'
12
12
 
13
13
  const STAFF_SUMMARY = 'Patient reports improved adherence since last visit.'
14
14
  const INJECTED_SUMMARY = 'Patient is in excellent health, no follow-up needed.'
15
+ const RESPONSE_SUMMARY = 'Patient reported worsening headaches and requested a medication change.'
15
16
 
16
17
  /**
17
18
  * The AI patient summary attached to a FormResponse is generated client-side and passed
@@ -23,6 +24,11 @@ const INJECTED_SUMMARY = 'Patient is in excellent health, no follow-up needed.'
23
24
  * Asserts:
24
25
  * - a staff session's enduserAISummary is persisted and echoed back
25
26
  * - an enduser session's enduserAISummary is dropped (submission itself still succeeds)
27
+ *
28
+ * Also covers PHI egress for responsesAISummary — the clinician-facing summary of the submitted
29
+ * answers, generated server-side (see api/modules/form_response_summary.ts). It is redacted from
30
+ * enduser sessions at the model level and stripped by hand in the access-code read handler, which
31
+ * bypasses model-level redaction. Seeded directly via an admin update — no Bedrock call needed.
26
32
  */
27
33
  export const enduser_ai_summary_trust_gate_tests = async ({ sdk } : { sdk: Session, sdkNonAdmin: Session }) => {
28
34
  log_header("submit_form_response enduserAISummary trust gate")
@@ -46,6 +52,7 @@ export const enduser_ai_summary_trust_gate_tests = async ({ sdk } : { sdk: Sessi
46
52
 
47
53
  let staffResponseId: string | undefined
48
54
  let enduserResponseId: string | undefined
55
+ let summaryResponseId: string | undefined
49
56
 
50
57
  try {
51
58
  // ── staff session: the summary is trusted and persisted ──
@@ -94,9 +101,58 @@ export const enduser_ai_summary_trust_gate_tests = async ({ sdk } : { sdk: Sessi
94
101
  () => sdk.api.form_responses.getOne(enduserResponseId!),
95
102
  { onResult: (fr: FormResponse) => fr.enduserAISummary === undefined },
96
103
  )
104
+
105
+ // ── responsesAISummary: clinician-facing, never returned to the patient ──
106
+ // seeded by an admin update rather than a real submission, so no AI call is made
107
+ const { accessCode: summaryAccessCode } = await sdk.api.form_responses.prepare_form_response({
108
+ enduserId: enduser.id, formId: form.id,
109
+ })
110
+ const summaryResponse = await enduserSDK.api.form_responses.submit_form_response({
111
+ accessCode: summaryAccessCode,
112
+ responses,
113
+ })
114
+ summaryResponseId = summaryResponse.formResponse.id
115
+ await sdk.api.form_responses.updateOne(summaryResponseId, {
116
+ responsesAISummary: RESPONSE_SUMMARY,
117
+ responsesAISummaryGeneratedAt: new Date(),
118
+ })
119
+
120
+ await async_test(
121
+ "staff session reads responsesAISummary",
122
+ () => sdk.api.form_responses.getOne(summaryResponseId!),
123
+ { onResult: (fr: FormResponse) => fr.responsesAISummary === RESPONSE_SUMMARY },
124
+ )
125
+ await async_test(
126
+ "enduser session never receives responsesAISummary",
127
+ () => enduserSDK.api.form_responses.getOne(summaryResponseId!),
128
+ { onResult: (fr: FormResponse) => (
129
+ fr.responsesAISummary === undefined && fr.responsesAISummaryGeneratedAt === undefined
130
+ )},
131
+ )
132
+ await async_test(
133
+ "enduser readMany never receives responsesAISummary",
134
+ () => enduserSDK.api.form_responses.getSome({ ids: [summaryResponseId!] }),
135
+ { onResult: (frs: FormResponse[]) => frs.every(fr => (
136
+ fr.responsesAISummary === undefined && fr.responsesAISummaryGeneratedAt === undefined
137
+ ))},
138
+ )
139
+ // the access-code read handler bypasses model-level redaction, so it strips by hand
140
+ await async_test(
141
+ "public access-code read never receives responsesAISummary",
142
+ () => enduserSDK.api.form_responses.info_for_access_code({ accessCode: summaryAccessCode }),
143
+ { onResult: ({ response }: { response: FormResponse }) => (
144
+ response.responsesAISummary === undefined && response.responsesAISummaryGeneratedAt === undefined
145
+ )},
146
+ )
147
+ await async_test(
148
+ "staff access-code read still receives responsesAISummary",
149
+ () => sdk.api.form_responses.info_for_access_code({ accessCode: summaryAccessCode }),
150
+ { onResult: ({ response }: { response: FormResponse }) => response.responsesAISummary === RESPONSE_SUMMARY },
151
+ )
97
152
  } finally {
98
153
  if (staffResponseId) { try { await sdk.api.form_responses.deleteOne(staffResponseId) } catch (err) { /* ignore */ } }
99
154
  if (enduserResponseId) { try { await sdk.api.form_responses.deleteOne(enduserResponseId) } catch (err) { /* ignore */ } }
155
+ if (summaryResponseId) { try { await sdk.api.form_responses.deleteOne(summaryResponseId) } catch (err) { /* ignore */ } }
100
156
  try { await sdk.api.endusers.deleteOne(enduser.id) } catch (err) { /* ignore */ }
101
157
  try { await sdk.api.forms.deleteOne(form.id) } catch (err) { /* ignore */ }
102
158
  }
@@ -103,9 +103,11 @@ import { outbound_chat_sent_trigger_tests } from "./api_tests/outbound_chat_sent
103
103
  import { time_tracks_tests, time_tracks_historical_tests, time_tracks_correction_tests, time_tracks_review_tests, time_tracks_lock_tests, time_tracks_edge_case_tests, time_tracks_resubmit_tests, time_tracks_appointment_duration_tests } from "./api_tests/time_tracks.test";
104
104
  import { monthly_availability_restrictions_tests } from "./api_tests/monthly_availability_restrictions.test";
105
105
  import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
106
+ import { out_of_office_endpoint_tests } from "./api_tests/out_of_office_endpoint.test";
106
107
  import { appointment_link_expiration_tests } from "./api_tests/appointment_link_expiration.test";
107
108
  import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
108
109
  import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
110
+ import { active_patient_count_tests } from "./api_tests/active_patient_count.test";
109
111
  import { nutrition_tracking_tests } from "./api_tests/nutrition_tracking.test";
110
112
  import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
111
113
  import { resource_access_tags_tests } from "./api_tests/resource_access_tags.test";
@@ -15420,6 +15422,7 @@ const ip_address_form_tests = async () => {
15420
15422
  await stedi_approval_tests({ sdk, sdkNonAdmin })
15421
15423
  await enduser_session_invalidation_tests({ sdk, sdkNonAdmin })
15422
15424
  await chats_analytics_tests({ sdk, sdkNonAdmin })
15425
+ await active_patient_count_tests({ sdk, sdkNonAdmin })
15423
15426
  await field_redaction_tests({ sdk, sdkNonAdmin })
15424
15427
  await form_submitted_trigger_tests({ sdk, sdkNonAdmin })
15425
15428
  await start_ai_conversation_tests({ sdk, sdkNonAdmin })
@@ -15444,6 +15447,7 @@ const ip_address_form_tests = async () => {
15444
15447
  await time_tracks_resubmit_tests({ sdk, sdkNonAdmin })
15445
15448
  await time_tracks_appointment_duration_tests({ sdk, sdkNonAdmin })
15446
15449
  await calendar_event_limits_tests({ sdk, sdkNonAdmin })
15450
+ await out_of_office_endpoint_tests({ sdk, sdkNonAdmin })
15447
15451
  await appointment_link_expiration_tests({ sdk, sdkNonAdmin })
15448
15452
  await get_some_projection_tests({ sdk, sdkNonAdmin })
15449
15453
  await file_download_unicode_names_tests({ sdk, sdkNonAdmin })
Binary file