@tellescope/sdk 1.256.10 → 1.256.11

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 (38) hide show
  1. package/lib/cjs/sdk.d.ts +2 -2
  2. package/lib/cjs/tests/api_tests/generate_suggested_reply.test.d.ts.map +1 -0
  3. package/lib/cjs/tests/api_tests/security/suggested-reply-redaction.test.d.ts +26 -0
  4. package/lib/cjs/tests/api_tests/security/suggested-reply-redaction.test.d.ts.map +1 -0
  5. package/lib/cjs/tests/api_tests/security/suggested-reply-redaction.test.js +336 -0
  6. package/lib/cjs/tests/api_tests/security/suggested-reply-redaction.test.js.map +1 -0
  7. package/lib/cjs/tests/api_tests/stedi_approval.test.d.ts +6 -0
  8. package/lib/cjs/tests/api_tests/stedi_approval.test.d.ts.map +1 -0
  9. package/lib/cjs/tests/api_tests/stedi_approval.test.js +205 -0
  10. package/lib/cjs/tests/api_tests/stedi_approval.test.js.map +1 -0
  11. package/lib/cjs/tests/tests.d.ts.map +1 -1
  12. package/lib/cjs/tests/tests.js +236 -203
  13. package/lib/cjs/tests/tests.js.map +1 -1
  14. package/lib/esm/enduser.d.ts +0 -1
  15. package/lib/esm/enduser.d.ts.map +1 -1
  16. package/lib/esm/sdk.d.ts +4 -5
  17. package/lib/esm/sdk.d.ts.map +1 -1
  18. package/lib/esm/session.d.ts +0 -1
  19. package/lib/esm/session.d.ts.map +1 -1
  20. package/lib/esm/tests/api_tests/generate_suggested_reply.test.d.ts.map +1 -0
  21. package/lib/esm/tests/api_tests/security/suggested-reply-redaction.test.d.ts +26 -0
  22. package/lib/esm/tests/api_tests/security/suggested-reply-redaction.test.d.ts.map +1 -0
  23. package/lib/esm/tests/api_tests/security/suggested-reply-redaction.test.js +332 -0
  24. package/lib/esm/tests/api_tests/security/suggested-reply-redaction.test.js.map +1 -0
  25. package/lib/esm/tests/api_tests/stedi_approval.test.d.ts +6 -0
  26. package/lib/esm/tests/api_tests/stedi_approval.test.d.ts.map +1 -0
  27. package/lib/esm/tests/api_tests/stedi_approval.test.js +201 -0
  28. package/lib/esm/tests/api_tests/stedi_approval.test.js.map +1 -0
  29. package/lib/esm/tests/tests.d.ts.map +1 -1
  30. package/lib/esm/tests/tests.js +236 -203
  31. package/lib/esm/tests/tests.js.map +1 -1
  32. package/lib/tsconfig.tsbuildinfo +1 -1
  33. package/package.json +10 -10
  34. package/src/tests/api_tests/security/readonly-enduser-preview.test.ts +301 -0
  35. package/src/tests/api_tests/security/suggested-reply-redaction.test.ts +232 -0
  36. package/src/tests/api_tests/stedi_approval.test.ts +167 -0
  37. package/src/tests/tests.ts +34 -13
  38. package/test_generated.pdf +0 -0
package/lib/cjs/sdk.d.ts CHANGED
@@ -4193,7 +4193,7 @@ export declare class Session extends SessionManager {
4193
4193
  iat: number;
4194
4194
  exp: number;
4195
4195
  requiresMFA?: boolean | undefined;
4196
- sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token")[] | undefined;
4196
+ sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview")[] | undefined;
4197
4197
  scopeContext?: import("@tellescope/types-models").SessionScopeContext | undefined;
4198
4198
  allowedPaths?: string[] | undefined;
4199
4199
  users?: number | undefined;
@@ -4358,7 +4358,7 @@ export declare class Session extends SessionManager {
4358
4358
  iat: number;
4359
4359
  exp: number;
4360
4360
  requiresMFA?: boolean | undefined;
4361
- sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token")[] | undefined;
4361
+ sessionScopes?: ("video-join-link" | "video-start-link" | "public-form" | "appointment-booking" | "ics-download" | "embeddables-token" | "portal-preview")[] | undefined;
4362
4362
  scopeContext?: import("@tellescope/types-models").SessionScopeContext | undefined;
4363
4363
  allowedPaths?: string[] | undefined;
4364
4364
  users?: number | undefined;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate_suggested_reply.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/generate_suggested_reply.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAiBnC,eAAO,MAAM,8BAA8B;SAAwC,OAAO;iBAAe,OAAO;mBAgR/G,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { Session } from "../../../sdk";
2
+ /**
3
+ * Security regressions for the generateSuggestedReply journey step.
4
+ *
5
+ * `suggestedReply` holds a staff-facing draft that may be AI-generated and unreviewed, built from the
6
+ * patient's own chart context. Four defects were fixed:
7
+ *
8
+ * 1. emails / sms_messages / group_mms_conversations `suggestedReply` had no `redactions: ['enduser']`
9
+ * (only the sibling `suggestedReplyIsAIGenerated` flag did, so content leaked but the "machine
10
+ * generated" marker was stripped).
11
+ * 2. POST /v1/bulk-actions/read admitted enduser sessions via schema.users.enduserActions.readMany but
12
+ * never checked the REQUESTED model's enduserActions — so any model in the enduser query map was
13
+ * readable, regardless of whether it grants endusers read.
14
+ * 3. chat_rooms.mark_read spread the whole room with no applyRedactions, bypassing the redaction that
15
+ * *was* declared. The patient portal calls mark_read on every chat view.
16
+ * 4. generateSuggestedReply accepted an OUTBOUND message as its target (journeyContext carries outbound
17
+ * ids for the Message Delivery Failure and Message Link Clicked triggers).
18
+ *
19
+ * NO BEDROCK: drafts are written directly with a staff updateOne, and the fix-4 case returns from the
20
+ * inbound guard before the context load / Bedrock call are reached. Deterministic, consumes no AI credits.
21
+ */
22
+ export declare const suggested_reply_redaction_tests: ({ sdk }: {
23
+ sdk: Session;
24
+ sdkNonAdmin: Session;
25
+ }) => Promise<void>;
26
+ //# sourceMappingURL=suggested-reply-redaction.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggested-reply-redaction.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/suggested-reply-redaction.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAStC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,+BAA+B;SAA2B,OAAO;iBAAe,OAAO;mBAmLnG,CAAA"}
@@ -0,0 +1,336 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.suggested_reply_redaction_tests = void 0;
40
+ require('source-map-support').install();
41
+ var sdk_1 = require("../../../sdk");
42
+ var schema_1 = require("@tellescope/schema");
43
+ var testing_1 = require("@tellescope/testing");
44
+ var setup_1 = require("../../setup");
45
+ var host = process.env.API_URL || 'http://localhost:8080';
46
+ var DRAFT = 'STAFF-ONLY-DRAFT-do-not-show-the-patient';
47
+ /**
48
+ * Security regressions for the generateSuggestedReply journey step.
49
+ *
50
+ * `suggestedReply` holds a staff-facing draft that may be AI-generated and unreviewed, built from the
51
+ * patient's own chart context. Four defects were fixed:
52
+ *
53
+ * 1. emails / sms_messages / group_mms_conversations `suggestedReply` had no `redactions: ['enduser']`
54
+ * (only the sibling `suggestedReplyIsAIGenerated` flag did, so content leaked but the "machine
55
+ * generated" marker was stripped).
56
+ * 2. POST /v1/bulk-actions/read admitted enduser sessions via schema.users.enduserActions.readMany but
57
+ * never checked the REQUESTED model's enduserActions — so any model in the enduser query map was
58
+ * readable, regardless of whether it grants endusers read.
59
+ * 3. chat_rooms.mark_read spread the whole room with no applyRedactions, bypassing the redaction that
60
+ * *was* declared. The patient portal calls mark_read on every chat view.
61
+ * 4. generateSuggestedReply accepted an OUTBOUND message as its target (journeyContext carries outbound
62
+ * ids for the Message Delivery Failure and Message Link Clicked triggers).
63
+ *
64
+ * NO BEDROCK: drafts are written directly with a staff updateOne, and the fix-4 case returns from the
65
+ * inbound guard before the context load / Bedrock call are reached. Deterministic, consumes no AI credits.
66
+ */
67
+ var suggested_reply_redaction_tests = function (_a) {
68
+ var sdk = _a.sdk;
69
+ return __awaiter(void 0, void 0, void 0, function () {
70
+ var enduserId, emailId, inboundSMSId, outboundSMSId, roomId, journeyId, enduser, email, inboundSMS, outboundSMS, room, _i, _b, _c, model, id, roomAsAdmin, emailAsAdmin, smsAsAdmin, authToken, asEnduser_1, roomAsEnduser, roomsAsEnduser, foundRoom, bulk, bulkAsStaff, _d, _e, model, field, journey, step, automatedAction, processResult, outboundAfter, _f, _g, _h, _j, _k, _l;
71
+ var _m, _o, _p, _q;
72
+ return __generator(this, function (_r) {
73
+ switch (_r.label) {
74
+ case 0:
75
+ (0, testing_1.log_header)("Suggested Reply redaction + inbound guard");
76
+ _r.label = 1;
77
+ case 1:
78
+ _r.trys.push([1, , 25, 50]);
79
+ return [4 /*yield*/, sdk.api.endusers.createOne({
80
+ fname: 'SRRedaction', lname: 'Test', phone: '+15555550188',
81
+ email: "sr-redaction-".concat(Date.now(), "@example.com"),
82
+ })];
83
+ case 2:
84
+ enduser = _r.sent();
85
+ enduserId = enduser.id;
86
+ return [4 /*yield*/, sdk.api.emails.createOne({
87
+ enduserId: enduserId,
88
+ subject: 'SR seed', textContent: 'seed', logOnly: true, inbound: true,
89
+ })];
90
+ case 3:
91
+ email = _r.sent();
92
+ emailId = email.id;
93
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
94
+ enduserId: enduserId,
95
+ message: 'inbound seed', logOnly: true, inbound: true,
96
+ })];
97
+ case 4:
98
+ inboundSMS = _r.sent();
99
+ inboundSMSId = inboundSMS.id;
100
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
101
+ enduserId: enduserId,
102
+ message: 'outbound seed', logOnly: true, inbound: false,
103
+ })];
104
+ case 5:
105
+ outboundSMS = _r.sent();
106
+ outboundSMSId = outboundSMS.id;
107
+ return [4 /*yield*/, sdk.api.chat_rooms.createOne({
108
+ type: 'internal', userIds: [], enduserIds: [enduserId], title: 'SR redaction room',
109
+ })];
110
+ case 6:
111
+ room = _r.sent();
112
+ roomId = room.id;
113
+ _i = 0, _b = [['emails', emailId], ['sms_messages', inboundSMSId], ['chat_rooms', roomId]];
114
+ _r.label = 7;
115
+ case 7:
116
+ if (!(_i < _b.length)) return [3 /*break*/, 10];
117
+ _c = _b[_i], model = _c[0], id = _c[1];
118
+ return [4 /*yield*/, sdk.api[model].updateOne(id, { suggestedReply: DRAFT, suggestedReplyIsAIGenerated: true })];
119
+ case 8:
120
+ _r.sent();
121
+ _r.label = 9;
122
+ case 9:
123
+ _i++;
124
+ return [3 /*break*/, 7];
125
+ case 10: return [4 /*yield*/, sdk.api.chat_rooms.getOne(roomId)];
126
+ case 11:
127
+ roomAsAdmin = _r.sent();
128
+ return [4 /*yield*/, sdk.api.emails.getOne(emailId)];
129
+ case 12:
130
+ emailAsAdmin = _r.sent();
131
+ return [4 /*yield*/, sdk.api.sms_messages.getOne(inboundSMSId)];
132
+ case 13:
133
+ smsAsAdmin = _r.sent();
134
+ (0, testing_1.assert)(roomAsAdmin.suggestedReply === DRAFT && roomAsAdmin.suggestedReplyIsAIGenerated === true
135
+ && emailAsAdmin.suggestedReply === DRAFT && smsAsAdmin.suggestedReply === DRAFT, 'drafts did not persist / are not visible to staff — the API server is likely running a stale '
136
+ + '@tellescope/schema, so the redaction assertions below would pass spuriously. Restart it.', 'CONTROL: drafts persist and staff can read them on all three models');
137
+ return [4 /*yield*/, sdk.api.endusers.generate_auth_token({ id: enduserId })];
138
+ case 14:
139
+ authToken = (_r.sent()).authToken;
140
+ asEnduser_1 = new sdk_1.Session({ host: host });
141
+ asEnduser_1.setAuthToken(authToken);
142
+ /*************** Fix 3: mark_read must redact ***************/
143
+ return [4 /*yield*/, (0, testing_1.async_test)('chat_rooms.mark_read does not leak suggestedReply to the patient', function () { return asEnduser_1.api.chat_rooms.mark_read({ id: roomId }); }, {
144
+ onResult: function (r) {
145
+ var _a, _b;
146
+ var updated = r === null || r === void 0 ? void 0 : r.updated;
147
+ if (!updated)
148
+ return false;
149
+ // unreadCount proves the handler still did its job rather than erroring out
150
+ var stillWorks = ((_b = (_a = updated.infoForUser) === null || _a === void 0 ? void 0 : _a[enduserId]) === null || _b === void 0 ? void 0 : _b.unreadCount) === 0;
151
+ return stillWorks
152
+ && updated.suggestedReply === undefined
153
+ && updated.suggestedReplyIsAIGenerated === undefined;
154
+ },
155
+ })
156
+ /*************** Fix 1: plain reads on chat_rooms must redact ***************/
157
+ ];
158
+ case 15:
159
+ /*************** Fix 3: mark_read must redact ***************/
160
+ _r.sent();
161
+ return [4 /*yield*/, asEnduser_1.api.chat_rooms.getOne(roomId)];
162
+ case 16:
163
+ roomAsEnduser = _r.sent();
164
+ (0, testing_1.assert)(roomAsEnduser.suggestedReply === undefined && roomAsEnduser.suggestedReplyIsAIGenerated === undefined, "enduser read chat_rooms.suggestedReply: ".concat(roomAsEnduser.suggestedReply), 'chat_rooms.getOne redacts suggestedReply for endusers');
165
+ return [4 /*yield*/, asEnduser_1.api.chat_rooms.getSome({ limit: 50 })];
166
+ case 17:
167
+ roomsAsEnduser = _r.sent();
168
+ foundRoom = roomsAsEnduser.find(function (r) { return r.id === roomId; });
169
+ (0, testing_1.assert)(!!foundRoom && foundRoom.suggestedReply === undefined, 'enduser readMany leaked chat_rooms.suggestedReply', 'chat_rooms.getSome redacts suggestedReply for endusers');
170
+ return [4 /*yield*/, asEnduser_1.bulk_load({
171
+ load: [{ model: 'emails' }, { model: 'sms_messages' }, { model: 'chat_rooms' }],
172
+ })];
173
+ case 18:
174
+ bulk = _r.sent();
175
+ (0, testing_1.assert)(bulk.results[0] === null && bulk.results[1] === null, "bulk_load exposed models without enduser readMany: emails=".concat(JSON.stringify(bulk.results[0]), " sms=").concat(JSON.stringify(bulk.results[1])), 'bulk_load returns null for models with no enduser readMany (emails, sms_messages)');
176
+ (0, testing_1.assert)(!!((_m = bulk.results[2]) === null || _m === void 0 ? void 0 : _m.records) && !bulk.results[2].records.some(function (r) { return r.suggestedReply !== undefined; }), 'bulk_load leaked chat_rooms.suggestedReply', 'bulk_load still returns chat_rooms for endusers, with suggestedReply redacted');
177
+ return [4 /*yield*/, sdk.bulk_load({ load: [{ model: 'emails' }] })];
178
+ case 19:
179
+ bulkAsStaff = _r.sent();
180
+ (0, testing_1.assert)(!!((_o = bulkAsStaff.results[0]) === null || _o === void 0 ? void 0 : _o.records) && bulkAsStaff.results[0].records.length > 0, 'bulk_load stopped returning emails for staff — the enduser gate leaked into staff sessions', 'bulk_load unchanged for staff sessions');
181
+ /*************** Fix 1 (defense-in-depth): redaction is declared in schema ***************/
182
+ // Once the bulk-read gate is in place, emails/sms_messages are unreachable by enduser sessions, so
183
+ // their redaction is no longer observable end-to-end. Assert it structurally so it survives the
184
+ // gate ever being relaxed.
185
+ for (_d = 0, _e = ['emails', 'sms_messages', 'group_mms_conversations']; _d < _e.length; _d++) {
186
+ model = _e[_d];
187
+ field = schema_1.schema[model].fields.suggestedReply;
188
+ (0, testing_1.assert)(!!((_p = field === null || field === void 0 ? void 0 : field.redactions) === null || _p === void 0 ? void 0 : _p.includes('enduser')), "".concat(model, ".suggestedReply is missing redactions: ['enduser']"), "".concat(model, ".suggestedReply declares an enduser redaction"));
189
+ }
190
+ return [4 /*yield*/, sdk.api.journeys.createOne({ title: "SR Inbound Guard ".concat(Date.now()) })];
191
+ case 20:
192
+ journey = _r.sent();
193
+ journeyId = journey.id;
194
+ return [4 /*yield*/, sdk.api.automation_steps.createOne({
195
+ journeyId: journeyId,
196
+ events: [{ type: 'onJourneyStart', info: {} }],
197
+ action: { type: 'generateSuggestedReply', info: {} },
198
+ })];
199
+ case 21:
200
+ step = _r.sent();
201
+ return [4 /*yield*/, sdk.api.automated_actions.createOne({
202
+ enduserId: enduserId,
203
+ journeyId: journeyId,
204
+ automationStepId: step.id,
205
+ event: { type: 'onJourneyStart', info: {} },
206
+ action: { type: 'generateSuggestedReply', info: {} },
207
+ status: 'active',
208
+ processAfter: Date.now(),
209
+ journeyContext: { smsId: outboundSMSId },
210
+ })
211
+ // returns before loadAISummaryContextFromDB / Bedrock.sendMessage — no AI credits consumed
212
+ ];
213
+ case 22:
214
+ automatedAction = _r.sent();
215
+ return [4 /*yield*/, sdk.api.automated_actions.process({ automatedActionId: automatedAction.id })];
216
+ case 23:
217
+ processResult = _r.sent();
218
+ return [4 /*yield*/, sdk.api.sms_messages.getOne(outboundSMSId)];
219
+ case 24:
220
+ outboundAfter = _r.sent();
221
+ (0, testing_1.assert)(!outboundAfter.suggestedReply, "a draft was written onto an OUTBOUND message: ".concat(outboundAfter.suggestedReply), 'outbound target is rejected without writing suggestedReply');
222
+ // success:false is what makes the worker throw — which marks the automated_action 'error', fires
223
+ // any onError branch, honors continueOnError, and logs the background_error. Returning
224
+ // success:true here would report a clean run and silently skip all of that. Asserted on the
225
+ // response rather than on background_errors because this calls the API directly, so the worker
226
+ // (which writes that row) is not in the loop.
227
+ (0, testing_1.assert)(processResult.success === false
228
+ && /outbound message, not an incoming one/i.test((_q = processResult.error) !== null && _q !== void 0 ? _q : ''), "expected success:false with an outbound-specific error, got: ".concat(JSON.stringify(processResult)), 'outbound rejection returns success:false so journey error handling engages');
229
+ return [3 /*break*/, 50];
230
+ case 25:
231
+ if (!journeyId) return [3 /*break*/, 29];
232
+ _r.label = 26;
233
+ case 26:
234
+ _r.trys.push([26, 28, , 29]);
235
+ return [4 /*yield*/, sdk.api.journeys.deleteOne(journeyId)];
236
+ case 27:
237
+ _r.sent();
238
+ return [3 /*break*/, 29];
239
+ case 28:
240
+ _f = _r.sent();
241
+ return [3 /*break*/, 29];
242
+ case 29:
243
+ if (!roomId) return [3 /*break*/, 33];
244
+ _r.label = 30;
245
+ case 30:
246
+ _r.trys.push([30, 32, , 33]);
247
+ return [4 /*yield*/, sdk.api.chat_rooms.deleteOne(roomId)];
248
+ case 31:
249
+ _r.sent();
250
+ return [3 /*break*/, 33];
251
+ case 32:
252
+ _g = _r.sent();
253
+ return [3 /*break*/, 33];
254
+ case 33:
255
+ if (!emailId) return [3 /*break*/, 37];
256
+ _r.label = 34;
257
+ case 34:
258
+ _r.trys.push([34, 36, , 37]);
259
+ return [4 /*yield*/, sdk.api.emails.deleteOne(emailId)];
260
+ case 35:
261
+ _r.sent();
262
+ return [3 /*break*/, 37];
263
+ case 36:
264
+ _h = _r.sent();
265
+ return [3 /*break*/, 37];
266
+ case 37:
267
+ if (!inboundSMSId) return [3 /*break*/, 41];
268
+ _r.label = 38;
269
+ case 38:
270
+ _r.trys.push([38, 40, , 41]);
271
+ return [4 /*yield*/, sdk.api.sms_messages.deleteOne(inboundSMSId)];
272
+ case 39:
273
+ _r.sent();
274
+ return [3 /*break*/, 41];
275
+ case 40:
276
+ _j = _r.sent();
277
+ return [3 /*break*/, 41];
278
+ case 41:
279
+ if (!outboundSMSId) return [3 /*break*/, 45];
280
+ _r.label = 42;
281
+ case 42:
282
+ _r.trys.push([42, 44, , 45]);
283
+ return [4 /*yield*/, sdk.api.sms_messages.deleteOne(outboundSMSId)];
284
+ case 43:
285
+ _r.sent();
286
+ return [3 /*break*/, 45];
287
+ case 44:
288
+ _k = _r.sent();
289
+ return [3 /*break*/, 45];
290
+ case 45:
291
+ if (!enduserId) return [3 /*break*/, 49];
292
+ _r.label = 46;
293
+ case 46:
294
+ _r.trys.push([46, 48, , 49]);
295
+ return [4 /*yield*/, sdk.api.endusers.deleteOne(enduserId)];
296
+ case 47:
297
+ _r.sent();
298
+ return [3 /*break*/, 49];
299
+ case 48:
300
+ _l = _r.sent();
301
+ return [3 /*break*/, 49];
302
+ case 49: return [7 /*endfinally*/];
303
+ case 50: return [2 /*return*/];
304
+ }
305
+ });
306
+ });
307
+ };
308
+ exports.suggested_reply_redaction_tests = suggested_reply_redaction_tests;
309
+ if (require.main === module) {
310
+ console.log("\uD83C\uDF10 Using API URL: ".concat(host));
311
+ var sdk_2 = new sdk_1.Session({ host: host });
312
+ var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
313
+ var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
314
+ return __generator(this, function (_a) {
315
+ switch (_a.label) {
316
+ case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
317
+ case 1:
318
+ _a.sent();
319
+ return [4 /*yield*/, (0, exports.suggested_reply_redaction_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
320
+ case 2:
321
+ _a.sent();
322
+ return [2 /*return*/];
323
+ }
324
+ });
325
+ }); };
326
+ runTests()
327
+ .then(function () {
328
+ console.log("✅ Suggested Reply redaction test suite completed successfully");
329
+ process.exit(0);
330
+ })
331
+ .catch(function (error) {
332
+ console.error("❌ Suggested Reply redaction test suite failed:", error);
333
+ process.exit(1);
334
+ });
335
+ }
336
+ //# sourceMappingURL=suggested-reply-redaction.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggested-reply-redaction.test.js","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/suggested-reply-redaction.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { Session } from "../../sdk";
2
+ export declare const stedi_approval_tests: ({ sdk, sdkNonAdmin }: {
3
+ sdk: Session;
4
+ sdkNonAdmin: Session;
5
+ }) => Promise<void>;
6
+ //# sourceMappingURL=stedi_approval.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stedi_approval.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/stedi_approval.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAkB,MAAM,WAAW,CAAA;AAenD,eAAO,MAAM,oBAAoB;SAAwC,OAAO;iBAAe,OAAO;mBA+HrG,CAAA"}
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.stedi_approval_tests = void 0;
40
+ require('source-map-support').install();
41
+ var sdk_1 = require("../../sdk");
42
+ var testing_1 = require("@tellescope/testing");
43
+ var constants_1 = require("@tellescope/constants");
44
+ var setup_1 = require("../setup");
45
+ var host = process.env.API_URL || 'http://localhost:8080';
46
+ // Stedi runs on Tellescope's own platform credentials (zz_secrets) and each eligibility check costs
47
+ // Tellescope $0.10, so an organization must be approved by a Tellescope super admin
48
+ // (Organization.stediAllowed) before any Stedi call is made on its behalf.
49
+ //
50
+ // Every assertion here is a REJECTION assertion, so nothing in this file ever reaches Stedi.
51
+ var stedi_approval_tests = function (_a) {
52
+ var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
53
+ return __awaiter(void 0, void 0, void 0, function () {
54
+ var orgId, businessId, organization, enduser, enduserSdk_1, messageIsGenericForEnduser;
55
+ return __generator(this, function (_b) {
56
+ switch (_b.label) {
57
+ case 0:
58
+ (0, testing_1.log_header)("Stedi Pre-Approval (stediAllowed) Tests");
59
+ orgId = sdk.userInfo.businessId;
60
+ businessId = orgId;
61
+ // A. Super-admin write gate.
62
+ //
63
+ // `isa` is only minted by GET /switch-tenant, so this plainly-authenticated admin session never
64
+ // has it — even when TEST_EMAIL happens to be in the API's SUPER_ADMINS allowlist.
65
+ (0, testing_1.log_header)("A. stediAllowed is writable by super admins only");
66
+ return [4 /*yield*/, (0, testing_1.async_test)("org admin cannot enable stediAllowed for their own organization", function () { return sdk.api.organizations.updateOne(orgId, { stediAllowed: true }); }, { shouldError: true, onError: function (e) { return /not allowed/i.test(e.message); } })
67
+ // Regression test for the truthiness hole in the shared super-admin relationship constraint:
68
+ // it used to test `options.updates?.stediAllowed` (falsy for `false`), so an org admin could
69
+ // clear super-admin-owned flags even though they could never set them.
70
+ ];
71
+ case 1:
72
+ _b.sent();
73
+ // Regression test for the truthiness hole in the shared super-admin relationship constraint:
74
+ // it used to test `options.updates?.stediAllowed` (falsy for `false`), so an org admin could
75
+ // clear super-admin-owned flags even though they could never set them.
76
+ return [4 /*yield*/, (0, testing_1.async_test)("org admin cannot disable stediAllowed either (guard is key-presence, not truthiness)", function () { return sdk.api.organizations.updateOne(orgId, { stediAllowed: false }); }, { shouldError: true, onError: function (e) { return /not allowed/i.test(e.message); } })
77
+ // Same bug, pre-existing field — proves the fix wasn't scoped to the new flag only.
78
+ ];
79
+ case 2:
80
+ // Regression test for the truthiness hole in the shared super-admin relationship constraint:
81
+ // it used to test `options.updates?.stediAllowed` (falsy for `false`), so an org admin could
82
+ // clear super-admin-owned flags even though they could never set them.
83
+ _b.sent();
84
+ // Same bug, pre-existing field — proves the fix wasn't scoped to the new flag only.
85
+ return [4 /*yield*/, (0, testing_1.async_test)("org admin cannot disable bedrockAIAllowed", function () { return sdk.api.organizations.updateOne(orgId, { bedrockAIAllowed: false }); }, { shouldError: true, onError: function (e) { return /not allowed/i.test(e.message); } })
86
+ // ...and that it covers the whole gated list, not just the two booleans.
87
+ ];
88
+ case 3:
89
+ // Same bug, pre-existing field — proves the fix wasn't scoped to the new flag only.
90
+ _b.sent();
91
+ // ...and that it covers the whole gated list, not just the two booleans.
92
+ return [4 /*yield*/, (0, testing_1.async_test)("org admin cannot disable allowCreateSuborganizations", function () { return sdk.api.organizations.updateOne(orgId, { allowCreateSuborganizations: false }); }, { shouldError: true, onError: function (e) { return /not allowed/i.test(e.message); } })
93
+ // B. An unapproved organization is rejected at every Stedi entry point.
94
+ ];
95
+ case 4:
96
+ // ...and that it covers the whole gated list, not just the two booleans.
97
+ _b.sent();
98
+ // B. An unapproved organization is rejected at every Stedi entry point.
99
+ (0, testing_1.log_header)("B. Unapproved organizations cannot reach Stedi");
100
+ return [4 /*yield*/, sdk.api.organizations.getOne(orgId)];
101
+ case 5:
102
+ organization = _b.sent();
103
+ if (organization.stediAllowed) {
104
+ console.log("⚠️ SKIPPING section B: the test organization already has stediAllowed=true "
105
+ + "(hand-toggled in this dev database). Turn it off in the super admin console and re-run — "
106
+ + "these assertions would otherwise report a false pass.");
107
+ return [2 /*return*/];
108
+ }
109
+ return [4 /*yield*/, sdk.api.endusers.createOne({
110
+ email: "stedi-approval-".concat(Date.now(), "@test.tellescope.com"),
111
+ fname: 'Stedi',
112
+ lname: 'Approval',
113
+ })];
114
+ case 6:
115
+ enduser = _b.sent();
116
+ _b.label = 7;
117
+ case 7:
118
+ _b.trys.push([7, , 14, 16]);
119
+ return [4 /*yield*/, (0, testing_1.async_test)("staff: Stedi payer search (proxy_read) is rejected", function () { return sdk.api.integrations.proxy_read({ integration: constants_1.STEDI_TITLE, type: 'payers', query: 'aetna' }); }, { shouldError: true, onError: function (e) { return /not enabled for this organization/i.test(e.message); } })];
120
+ case 8:
121
+ _b.sent();
122
+ return [4 /*yield*/, (0, testing_1.async_test)("staff: Stedi payer importer (load_payers) is rejected", function () { return sdk.api.integrations.load_payers({ integration: constants_1.STEDI_TITLE, query: 'aetna' }); }, { shouldError: true, onError: function (e) { return /not enabled for this organization/i.test(e.message); } })];
123
+ case 9:
124
+ _b.sent();
125
+ return [4 /*yield*/, (0, testing_1.async_test)("staff: Stedi eligibility check is rejected on approval, before the credit checks", function () { return sdk.api.integrations.proxy_read({
126
+ integration: constants_1.STEDI_TITLE,
127
+ type: 'stedi-eligibility',
128
+ id: enduser.id,
129
+ query: JSON.stringify({ serviceCode: '30', npi: '1234567890' }),
130
+ }); }, {
131
+ shouldError: true,
132
+ // The absence of /credit/ is the real assertion: it proves the approval gate fires ahead of
133
+ // the credit gate, so an unapproved org is never told to go buy credits.
134
+ onError: function (e) { return (/not enabled for this organization/i.test(e.message) && !/credit/i.test(e.message)); },
135
+ })
136
+ // Enduser sessions reach both branches for real: StediEligibilityInput auto-runs the check, and
137
+ // InsuranceInput search-on-types against the payer branch. Approval/billing state must not leak
138
+ // to patients.
139
+ ];
140
+ case 10:
141
+ _b.sent();
142
+ enduserSdk_1 = new sdk_1.EnduserSession({ host: host, businessId: businessId });
143
+ return [4 /*yield*/, (0, setup_1.authenticate_enduser_via_token)(sdk, enduserSdk_1, { id: enduser.id })
144
+ // Exact-match on the generic copy: no "Stedi", no "credits", no "contact sales", no mention that
145
+ // approval is the reason. Note this is deliberately the SAME string the enduser-facing credit
146
+ // rejection uses, so it cannot prove which gate fired — the staff assertion above is what pins
147
+ // down the approval-before-credits ordering.
148
+ ];
149
+ case 11:
150
+ _b.sent();
151
+ messageIsGenericForEnduser = function (e) { return (e.message === 'Eligibility check is currently unavailable'); };
152
+ return [4 /*yield*/, (0, testing_1.async_test)("enduser: eligibility check rejected with a generic message (no approval/billing leak)", function () { return enduserSdk_1.api.integrations.proxy_read({
153
+ integration: constants_1.STEDI_TITLE,
154
+ type: 'stedi-eligibility',
155
+ query: JSON.stringify({ serviceCode: '30', npi: '1234567890' }),
156
+ }); }, { shouldError: true, onError: messageIsGenericForEnduser })];
157
+ case 12:
158
+ _b.sent();
159
+ return [4 /*yield*/, (0, testing_1.async_test)("enduser: payer search rejected with a generic message (no approval/billing leak)", function () { return enduserSdk_1.api.integrations.proxy_read({
160
+ integration: constants_1.STEDI_TITLE,
161
+ type: 'payers',
162
+ query: 'aetna',
163
+ }); }, { shouldError: true, onError: messageIsGenericForEnduser })];
164
+ case 13:
165
+ _b.sent();
166
+ return [3 /*break*/, 16];
167
+ case 14: return [4 /*yield*/, sdk.api.endusers.deleteOne(enduser.id).catch(console.error)];
168
+ case 15:
169
+ _b.sent();
170
+ return [7 /*endfinally*/];
171
+ case 16: return [2 /*return*/];
172
+ }
173
+ });
174
+ });
175
+ };
176
+ exports.stedi_approval_tests = stedi_approval_tests;
177
+ // Allow running this test file independently
178
+ if (require.main === module) {
179
+ console.log("Using API URL: ".concat(host));
180
+ var sdk_2 = new sdk_1.Session({ host: host });
181
+ var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
182
+ var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
183
+ return __generator(this, function (_a) {
184
+ switch (_a.label) {
185
+ case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
186
+ case 1:
187
+ _a.sent();
188
+ return [4 /*yield*/, (0, exports.stedi_approval_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
189
+ case 2:
190
+ _a.sent();
191
+ return [2 /*return*/];
192
+ }
193
+ });
194
+ }); };
195
+ runTests()
196
+ .then(function () {
197
+ console.log("✅ Stedi pre-approval tests completed successfully");
198
+ process.exit(0);
199
+ })
200
+ .catch(function (error) {
201
+ console.error("❌ Stedi pre-approval tests failed:", error);
202
+ process.exit(1);
203
+ });
204
+ }
205
+ //# sourceMappingURL=stedi_approval.test.js.map