@tellescope/sdk 1.254.0 → 1.255.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/lib/cjs/sdk.d.ts +4 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +5 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.d.ts +16 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.js +187 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js +443 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.js +254 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.js +226 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts +21 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js +362 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts +20 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.js +139 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts +18 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.js +156 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts +20 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.js +157 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.js.map +1 -0
- package/lib/cjs/tests/setup.d.ts.map +1 -1
- package/lib/cjs/tests/setup.js +20 -1
- package/lib/cjs/tests/setup.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +543 -282
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +6 -2
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +5 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/session.d.ts +1 -0
- package/lib/esm/session.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.d.ts +16 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.js +183 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.js.map +1 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js +439 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js.map +1 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.js +250 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.js.map +1 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.js +222 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts +21 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js +358 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts +20 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.js +135 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts +18 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.js +152 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts +20 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.js +150 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.js.map +1 -0
- package/lib/esm/tests/setup.d.ts.map +1 -1
- package/lib/esm/tests/setup.js +20 -1
- package/lib/esm/tests/setup.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +543 -282
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +11 -0
- package/src/tests/api_tests/mdi_case_offerings.test.ts +414 -0
- package/src/tests/api_tests/organization_api_keys.test.ts +207 -0
- package/src/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.ts +221 -0
- package/src/tests/api_tests/security/F-0145-globalunique-leak.test.ts +78 -0
- package/src/tests/api_tests/security/F-0151-load-inbox-redaction.test.ts +81 -0
- package/src/tests/api_tests/security/F-0155-webhook-timeout.test.ts +85 -0
- package/src/tests/setup.ts +9 -0
- package/src/tests/tests.ts +199 -2
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,362 @@
|
|
|
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.enduser_cross_create_tests = void 0;
|
|
40
|
+
require('source-map-support').install();
|
|
41
|
+
var sdk_1 = require("../../../sdk");
|
|
42
|
+
var testing_1 = require("@tellescope/testing");
|
|
43
|
+
var setup_1 = require("../../setup");
|
|
44
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
45
|
+
var businessId = '60398b1131a295e64f084ff6';
|
|
46
|
+
var ENDUSER_PASSWORD = 'F0116TestPassword!123';
|
|
47
|
+
var CROSS_ENDUSER_MESSAGE = "enduserId does not match creator id for enduser session";
|
|
48
|
+
/**
|
|
49
|
+
* Regression test for the enduser cross-enduser CREATE gating gaps:
|
|
50
|
+
* F-0116 enduser_observations (security-audit/findings/F-0116-*.md)
|
|
51
|
+
* F-0117 enduser_orders (security-audit/findings/F-0117-*.md)
|
|
52
|
+
* F-0119 managed_content_records (security-audit/findings/F-0119-*.md)
|
|
53
|
+
* F-0118 chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
|
|
54
|
+
*
|
|
55
|
+
* Each model exposed enduserActions.create with an `enduserId`/`enduserIds` field that
|
|
56
|
+
* lacked a write-side gate, letting an authenticated enduser create records bound to a
|
|
57
|
+
* DIFFERENT enduser in the same tenant. The fix adds a `constraints.relationship`
|
|
58
|
+
* evaluator mirroring the canonical `tickets` pattern (schema.ts).
|
|
59
|
+
*
|
|
60
|
+
* Methodology: each section asserts BOTH the exploit-is-blocked case AND that the
|
|
61
|
+
* legitimate path (self-create + staff-create) still works.
|
|
62
|
+
*/
|
|
63
|
+
var enduser_cross_create_tests = function (_a) {
|
|
64
|
+
var sdk = _a.sdk;
|
|
65
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
66
|
+
var attackerId, victimId, createdObservationIds, createdOrderIds, createdContentIds, createdRoomIds, attackerEmail, victimEmail, attacker, victim, attackerSDK_1, orderPayload_1, staffId_1, _i, createdRoomIds_1, id, _b, _c, createdContentIds_1, id, _d, _e, createdObservationIds_1, id, _f, _g, createdOrderIds_1, id, _h, _j, _k;
|
|
67
|
+
return __generator(this, function (_l) {
|
|
68
|
+
switch (_l.label) {
|
|
69
|
+
case 0:
|
|
70
|
+
(0, testing_1.log_header)("F-0116/F-0117/F-0118/F-0119: enduser cross-enduser create gates");
|
|
71
|
+
createdObservationIds = [];
|
|
72
|
+
createdOrderIds = [];
|
|
73
|
+
createdContentIds = [];
|
|
74
|
+
createdRoomIds = [];
|
|
75
|
+
_l.label = 1;
|
|
76
|
+
case 1:
|
|
77
|
+
_l.trys.push([1, , 21, 54]);
|
|
78
|
+
attackerEmail = "f0116-attacker-".concat(Date.now(), "@example.com");
|
|
79
|
+
victimEmail = "f0116-victim-".concat(Date.now(), "@example.com");
|
|
80
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({ email: attackerEmail, fname: 'F0116', lname: 'Attacker' })];
|
|
81
|
+
case 2:
|
|
82
|
+
attacker = _l.sent();
|
|
83
|
+
attackerId = attacker.id;
|
|
84
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({ email: victimEmail, fname: 'F0116', lname: 'Victim' })];
|
|
85
|
+
case 3:
|
|
86
|
+
victim = _l.sent();
|
|
87
|
+
victimId = victim.id;
|
|
88
|
+
return [4 /*yield*/, sdk.api.endusers.set_password({ id: attacker.id, password: ENDUSER_PASSWORD })];
|
|
89
|
+
case 4:
|
|
90
|
+
_l.sent();
|
|
91
|
+
attackerSDK_1 = new sdk_1.EnduserSession({ host: host, businessId: businessId });
|
|
92
|
+
return [4 /*yield*/, attackerSDK_1.authenticate(attackerEmail, ENDUSER_PASSWORD)
|
|
93
|
+
// ============================================================
|
|
94
|
+
// F-0116 — enduser_observations
|
|
95
|
+
// ============================================================
|
|
96
|
+
];
|
|
97
|
+
case 5:
|
|
98
|
+
_l.sent();
|
|
99
|
+
// ============================================================
|
|
100
|
+
// F-0116 — enduser_observations
|
|
101
|
+
// ============================================================
|
|
102
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0116: enduser cannot create observation on another enduser (createOne)", function () { return attackerSDK_1.api.enduser_observations.createOne({
|
|
103
|
+
enduserId: victimId, category: 'vital-signs', status: 'final',
|
|
104
|
+
measurement: { unit: 'mmHg', value: 220 },
|
|
105
|
+
}); }, { shouldError: true, onError: function (e) { return e.message === CROSS_ENDUSER_MESSAGE; } })];
|
|
106
|
+
case 6:
|
|
107
|
+
// ============================================================
|
|
108
|
+
// F-0116 — enduser_observations
|
|
109
|
+
// ============================================================
|
|
110
|
+
_l.sent();
|
|
111
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0116: enduser cannot create observation on another enduser (createMany)", function () { return attackerSDK_1.api.enduser_observations.createSome([{
|
|
112
|
+
enduserId: victimId, category: 'vital-signs', status: 'final',
|
|
113
|
+
measurement: { unit: 'mmHg', value: 220 },
|
|
114
|
+
}]); }, { shouldError: true, onError: function (e) { return e.message === CROSS_ENDUSER_MESSAGE; } })
|
|
115
|
+
// Positive control: enduser CAN create an observation on their OWN record
|
|
116
|
+
];
|
|
117
|
+
case 7:
|
|
118
|
+
_l.sent();
|
|
119
|
+
// Positive control: enduser CAN create an observation on their OWN record
|
|
120
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0116: enduser can still create observation on own record", function () { return attackerSDK_1.api.enduser_observations.createOne({
|
|
121
|
+
enduserId: attackerId, category: 'vital-signs', status: 'final',
|
|
122
|
+
measurement: { unit: 'mmHg', value: 120 },
|
|
123
|
+
}); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
124
|
+
createdObservationIds.push(o.id); return (o === null || o === void 0 ? void 0 : o.enduserId) === attackerId; } })
|
|
125
|
+
// Positive control: staff CAN create an observation on any tenant enduser
|
|
126
|
+
];
|
|
127
|
+
case 8:
|
|
128
|
+
// Positive control: enduser CAN create an observation on their OWN record
|
|
129
|
+
_l.sent();
|
|
130
|
+
// Positive control: staff CAN create an observation on any tenant enduser
|
|
131
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0116: staff can still create observation on any enduser", function () { return sdk.api.enduser_observations.createOne({
|
|
132
|
+
enduserId: victimId, category: 'vital-signs', status: 'final',
|
|
133
|
+
measurement: { unit: 'mmHg', value: 118 },
|
|
134
|
+
}); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
135
|
+
createdObservationIds.push(o.id); return (o === null || o === void 0 ? void 0 : o.enduserId) === victimId; } })
|
|
136
|
+
// ============================================================
|
|
137
|
+
// F-0117 — enduser_orders
|
|
138
|
+
// ============================================================
|
|
139
|
+
];
|
|
140
|
+
case 9:
|
|
141
|
+
// Positive control: staff CAN create an observation on any tenant enduser
|
|
142
|
+
_l.sent();
|
|
143
|
+
orderPayload_1 = function (enduserId) { return ({
|
|
144
|
+
enduserId: enduserId,
|
|
145
|
+
externalId: "f0117-".concat(Date.now()), source: 'f0117-source',
|
|
146
|
+
title: 'f0117 order', status: 'pending',
|
|
147
|
+
}); };
|
|
148
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0117: enduser cannot create order on another enduser", function () { return attackerSDK_1.api.enduser_orders.createOne(orderPayload_1(victimId)); }, { shouldError: true, onError: function (e) { return e.message === CROSS_ENDUSER_MESSAGE; } })];
|
|
149
|
+
case 10:
|
|
150
|
+
_l.sent();
|
|
151
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0117: enduser can still create order on own record", function () { return attackerSDK_1.api.enduser_orders.createOne(orderPayload_1(attackerId)); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
152
|
+
createdOrderIds.push(o.id); return (o === null || o === void 0 ? void 0 : o.enduserId) === attackerId; } })];
|
|
153
|
+
case 11:
|
|
154
|
+
_l.sent();
|
|
155
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0117: staff can still create order on any enduser", function () { return sdk.api.enduser_orders.createOne(orderPayload_1(victimId)); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
156
|
+
createdOrderIds.push(o.id); return (o === null || o === void 0 ? void 0 : o.enduserId) === victimId; } })
|
|
157
|
+
// ============================================================
|
|
158
|
+
// F-0119 — managed_content_records
|
|
159
|
+
// ============================================================
|
|
160
|
+
];
|
|
161
|
+
case 12:
|
|
162
|
+
_l.sent();
|
|
163
|
+
// ============================================================
|
|
164
|
+
// F-0119 — managed_content_records
|
|
165
|
+
// ============================================================
|
|
166
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0119: enduser cannot create content with allowUnauthenticatedAccess", function () { return attackerSDK_1.api.managed_content_records.createOne({
|
|
167
|
+
title: 'f0119 phishing', textContent: 'x', allowUnauthenticatedAccess: true,
|
|
168
|
+
}); }, { shouldError: true, onError: function (e) { return e.message === "allowUnauthenticatedAccess cannot be set by endusers"; } })];
|
|
169
|
+
case 13:
|
|
170
|
+
// ============================================================
|
|
171
|
+
// F-0119 — managed_content_records
|
|
172
|
+
// ============================================================
|
|
173
|
+
_l.sent();
|
|
174
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0119: enduser cannot create content with publicRead", function () { return attackerSDK_1.api.managed_content_records.createOne({
|
|
175
|
+
title: 'f0119 broadcast', textContent: 'x', publicRead: true,
|
|
176
|
+
}); }, { shouldError: true, onError: function (e) { return e.message === "publicRead cannot be set by endusers"; } })];
|
|
177
|
+
case 14:
|
|
178
|
+
_l.sent();
|
|
179
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0119: enduser cannot create content bound to another enduser", function () { return attackerSDK_1.api.managed_content_records.createOne({
|
|
180
|
+
title: 'f0119 cross', textContent: 'x', enduserId: victimId,
|
|
181
|
+
}); }, { shouldError: true, onError: function (e) { return e.message === CROSS_ENDUSER_MESSAGE; } })];
|
|
182
|
+
case 15:
|
|
183
|
+
_l.sent();
|
|
184
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0119: enduser can still create ordinary content", function () { return attackerSDK_1.api.managed_content_records.createOne({
|
|
185
|
+
title: 'f0119 ok', textContent: 'hello',
|
|
186
|
+
}); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
187
|
+
createdContentIds.push(o.id); return !(o === null || o === void 0 ? void 0 : o.publicRead) && !(o === null || o === void 0 ? void 0 : o.allowUnauthenticatedAccess); } })];
|
|
188
|
+
case 16:
|
|
189
|
+
_l.sent();
|
|
190
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0119: staff can still create public content", function () { return sdk.api.managed_content_records.createOne({
|
|
191
|
+
title: 'f0119 staff public', textContent: 'x', publicRead: true,
|
|
192
|
+
}); }, { onResult: function (o) { if (o === null || o === void 0 ? void 0 : o.id)
|
|
193
|
+
createdContentIds.push(o.id); return (o === null || o === void 0 ? void 0 : o.publicRead) === true; } })
|
|
194
|
+
// ============================================================
|
|
195
|
+
// F-0118 — chat_rooms (enduserIds-only gate; staff userIds targeting is by-design)
|
|
196
|
+
// ============================================================
|
|
197
|
+
];
|
|
198
|
+
case 17:
|
|
199
|
+
_l.sent();
|
|
200
|
+
staffId_1 = sdk.userInfo.id;
|
|
201
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0118: enduser cannot add another patient to a chat room (enduserIds)", function () { return attackerSDK_1.api.chat_rooms.createOne({
|
|
202
|
+
type: 'internal', enduserIds: [attackerId, victimId], userIds: [staffId_1],
|
|
203
|
+
}); }, { shouldError: true, onError: function (e) { return e.message === "enduserIds may only contain your own id for enduser session"; } })
|
|
204
|
+
// Positive control: patient CAN create a room with care-team staff + self (intended feature)
|
|
205
|
+
];
|
|
206
|
+
case 18:
|
|
207
|
+
_l.sent();
|
|
208
|
+
// Positive control: patient CAN create a room with care-team staff + self (intended feature)
|
|
209
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0118: enduser can still create a room with staff + self", function () { return attackerSDK_1.api.chat_rooms.createOne({
|
|
210
|
+
type: 'internal', enduserIds: [attackerId], userIds: [staffId_1],
|
|
211
|
+
}); }, { onResult: function (o) { var _a, _b; if (o === null || o === void 0 ? void 0 : o.id)
|
|
212
|
+
createdRoomIds.push(o.id); return ((_a = o === null || o === void 0 ? void 0 : o.enduserIds) === null || _a === void 0 ? void 0 : _a.length) === 1 && ((_b = o === null || o === void 0 ? void 0 : o.userIds) === null || _b === void 0 ? void 0 : _b.includes(staffId_1)); } })
|
|
213
|
+
// Positive control: staff can still create multi-patient rooms
|
|
214
|
+
];
|
|
215
|
+
case 19:
|
|
216
|
+
// Positive control: patient CAN create a room with care-team staff + self (intended feature)
|
|
217
|
+
_l.sent();
|
|
218
|
+
// Positive control: staff can still create multi-patient rooms
|
|
219
|
+
return [4 /*yield*/, (0, testing_1.async_test)("F-0118: staff can still create a room with multiple endusers", function () { return sdk.api.chat_rooms.createOne({
|
|
220
|
+
type: 'internal', enduserIds: [attackerId, victimId], userIds: [staffId_1],
|
|
221
|
+
}); }, { onResult: function (o) { var _a; if (o === null || o === void 0 ? void 0 : o.id)
|
|
222
|
+
createdRoomIds.push(o.id); return ((_a = o === null || o === void 0 ? void 0 : o.enduserIds) === null || _a === void 0 ? void 0 : _a.length) === 2; } })];
|
|
223
|
+
case 20:
|
|
224
|
+
// Positive control: staff can still create multi-patient rooms
|
|
225
|
+
_l.sent();
|
|
226
|
+
return [3 /*break*/, 54];
|
|
227
|
+
case 21:
|
|
228
|
+
_i = 0, createdRoomIds_1 = createdRoomIds;
|
|
229
|
+
_l.label = 22;
|
|
230
|
+
case 22:
|
|
231
|
+
if (!(_i < createdRoomIds_1.length)) return [3 /*break*/, 27];
|
|
232
|
+
id = createdRoomIds_1[_i];
|
|
233
|
+
_l.label = 23;
|
|
234
|
+
case 23:
|
|
235
|
+
_l.trys.push([23, 25, , 26]);
|
|
236
|
+
return [4 /*yield*/, sdk.api.chat_rooms.deleteOne(id)];
|
|
237
|
+
case 24:
|
|
238
|
+
_l.sent();
|
|
239
|
+
return [3 /*break*/, 26];
|
|
240
|
+
case 25:
|
|
241
|
+
_b = _l.sent();
|
|
242
|
+
return [3 /*break*/, 26];
|
|
243
|
+
case 26:
|
|
244
|
+
_i++;
|
|
245
|
+
return [3 /*break*/, 22];
|
|
246
|
+
case 27:
|
|
247
|
+
_c = 0, createdContentIds_1 = createdContentIds;
|
|
248
|
+
_l.label = 28;
|
|
249
|
+
case 28:
|
|
250
|
+
if (!(_c < createdContentIds_1.length)) return [3 /*break*/, 33];
|
|
251
|
+
id = createdContentIds_1[_c];
|
|
252
|
+
_l.label = 29;
|
|
253
|
+
case 29:
|
|
254
|
+
_l.trys.push([29, 31, , 32]);
|
|
255
|
+
return [4 /*yield*/, sdk.api.managed_content_records.deleteOne(id)];
|
|
256
|
+
case 30:
|
|
257
|
+
_l.sent();
|
|
258
|
+
return [3 /*break*/, 32];
|
|
259
|
+
case 31:
|
|
260
|
+
_d = _l.sent();
|
|
261
|
+
return [3 /*break*/, 32];
|
|
262
|
+
case 32:
|
|
263
|
+
_c++;
|
|
264
|
+
return [3 /*break*/, 28];
|
|
265
|
+
case 33:
|
|
266
|
+
_e = 0, createdObservationIds_1 = createdObservationIds;
|
|
267
|
+
_l.label = 34;
|
|
268
|
+
case 34:
|
|
269
|
+
if (!(_e < createdObservationIds_1.length)) return [3 /*break*/, 39];
|
|
270
|
+
id = createdObservationIds_1[_e];
|
|
271
|
+
_l.label = 35;
|
|
272
|
+
case 35:
|
|
273
|
+
_l.trys.push([35, 37, , 38]);
|
|
274
|
+
return [4 /*yield*/, sdk.api.enduser_observations.deleteOne(id)];
|
|
275
|
+
case 36:
|
|
276
|
+
_l.sent();
|
|
277
|
+
return [3 /*break*/, 38];
|
|
278
|
+
case 37:
|
|
279
|
+
_f = _l.sent();
|
|
280
|
+
return [3 /*break*/, 38];
|
|
281
|
+
case 38:
|
|
282
|
+
_e++;
|
|
283
|
+
return [3 /*break*/, 34];
|
|
284
|
+
case 39:
|
|
285
|
+
_g = 0, createdOrderIds_1 = createdOrderIds;
|
|
286
|
+
_l.label = 40;
|
|
287
|
+
case 40:
|
|
288
|
+
if (!(_g < createdOrderIds_1.length)) return [3 /*break*/, 45];
|
|
289
|
+
id = createdOrderIds_1[_g];
|
|
290
|
+
_l.label = 41;
|
|
291
|
+
case 41:
|
|
292
|
+
_l.trys.push([41, 43, , 44]);
|
|
293
|
+
return [4 /*yield*/, sdk.api.enduser_orders.deleteOne(id)];
|
|
294
|
+
case 42:
|
|
295
|
+
_l.sent();
|
|
296
|
+
return [3 /*break*/, 44];
|
|
297
|
+
case 43:
|
|
298
|
+
_h = _l.sent();
|
|
299
|
+
return [3 /*break*/, 44];
|
|
300
|
+
case 44:
|
|
301
|
+
_g++;
|
|
302
|
+
return [3 /*break*/, 40];
|
|
303
|
+
case 45:
|
|
304
|
+
if (!attackerId) return [3 /*break*/, 49];
|
|
305
|
+
_l.label = 46;
|
|
306
|
+
case 46:
|
|
307
|
+
_l.trys.push([46, 48, , 49]);
|
|
308
|
+
return [4 /*yield*/, sdk.api.endusers.deleteOne(attackerId)];
|
|
309
|
+
case 47:
|
|
310
|
+
_l.sent();
|
|
311
|
+
return [3 /*break*/, 49];
|
|
312
|
+
case 48:
|
|
313
|
+
_j = _l.sent();
|
|
314
|
+
return [3 /*break*/, 49];
|
|
315
|
+
case 49:
|
|
316
|
+
if (!victimId) return [3 /*break*/, 53];
|
|
317
|
+
_l.label = 50;
|
|
318
|
+
case 50:
|
|
319
|
+
_l.trys.push([50, 52, , 53]);
|
|
320
|
+
return [4 /*yield*/, sdk.api.endusers.deleteOne(victimId)];
|
|
321
|
+
case 51:
|
|
322
|
+
_l.sent();
|
|
323
|
+
return [3 /*break*/, 53];
|
|
324
|
+
case 52:
|
|
325
|
+
_k = _l.sent();
|
|
326
|
+
return [3 /*break*/, 53];
|
|
327
|
+
case 53: return [7 /*endfinally*/];
|
|
328
|
+
case 54: return [2 /*return*/];
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
});
|
|
332
|
+
};
|
|
333
|
+
exports.enduser_cross_create_tests = enduser_cross_create_tests;
|
|
334
|
+
// Allow running this test file independently
|
|
335
|
+
if (require.main === module) {
|
|
336
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
337
|
+
var sdk_2 = new sdk_1.Session({ host: host });
|
|
338
|
+
var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
|
|
339
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
340
|
+
return __generator(this, function (_a) {
|
|
341
|
+
switch (_a.label) {
|
|
342
|
+
case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
|
|
343
|
+
case 1:
|
|
344
|
+
_a.sent();
|
|
345
|
+
return [4 /*yield*/, (0, exports.enduser_cross_create_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
346
|
+
case 2:
|
|
347
|
+
_a.sent();
|
|
348
|
+
return [2 /*return*/];
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}); };
|
|
352
|
+
runTests()
|
|
353
|
+
.then(function () {
|
|
354
|
+
console.log("✅ F-0116/F-0117/F-0118/F-0119 enduser cross-create test suite completed successfully");
|
|
355
|
+
process.exit(0);
|
|
356
|
+
})
|
|
357
|
+
.catch(function (error) {
|
|
358
|
+
console.error("❌ enduser cross-create test suite failed:", error);
|
|
359
|
+
process.exit(1);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
//# sourceMappingURL=F-0116-F-0119-enduser-cross-create.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"F-0116-F-0119-enduser-cross-create.test.js","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Session } from "../../../sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Regression test for F-0145
|
|
4
|
+
* (security-audit/findings/F-0145-globalunique-conflict-leaks-cross-tenant-record.md).
|
|
5
|
+
*
|
|
6
|
+
* The create endpoint generator's unconditional globalUnique-enforcement block
|
|
7
|
+
* (routing.ts, "globalUnique should be enforced even if _overrideUnique is true")
|
|
8
|
+
* threw uniquenessError([{ existingRecord: matches[0] }]) with the RAW matched record.
|
|
9
|
+
* `findSomeByMatchAny_Global` deletes businessId, so the match is global; for `users`
|
|
10
|
+
* (globalUnique: ['email','phone']) the 409 body leaked the full record incl. hashedPass.
|
|
11
|
+
*
|
|
12
|
+
* Fix: redact existingRecord to { _id, businessId } like the safe validateUniquenessConstraints
|
|
13
|
+
* path. This reproduces the leak with a same-tenant collision (same code path) and asserts the
|
|
14
|
+
* 409 body's existingRecord exposes nothing beyond _id + businessId.
|
|
15
|
+
*/
|
|
16
|
+
export declare const globalunique_leak_tests: ({ sdk }: {
|
|
17
|
+
sdk: Session;
|
|
18
|
+
sdkNonAdmin: Session;
|
|
19
|
+
}) => Promise<void>;
|
|
20
|
+
//# sourceMappingURL=F-0145-globalunique-leak.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"F-0145-globalunique-leak.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0145-globalunique-leak.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAStC;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,uBAAuB;SAA2B,OAAO;iBAAe,OAAO;mBA+B3F,CAAA"}
|
|
@@ -0,0 +1,139 @@
|
|
|
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.globalunique_leak_tests = void 0;
|
|
40
|
+
require('source-map-support').install();
|
|
41
|
+
var sdk_1 = require("../../../sdk");
|
|
42
|
+
var testing_1 = require("@tellescope/testing");
|
|
43
|
+
var setup_1 = require("../../setup");
|
|
44
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
45
|
+
/**
|
|
46
|
+
* Regression test for F-0145
|
|
47
|
+
* (security-audit/findings/F-0145-globalunique-conflict-leaks-cross-tenant-record.md).
|
|
48
|
+
*
|
|
49
|
+
* The create endpoint generator's unconditional globalUnique-enforcement block
|
|
50
|
+
* (routing.ts, "globalUnique should be enforced even if _overrideUnique is true")
|
|
51
|
+
* threw uniquenessError([{ existingRecord: matches[0] }]) with the RAW matched record.
|
|
52
|
+
* `findSomeByMatchAny_Global` deletes businessId, so the match is global; for `users`
|
|
53
|
+
* (globalUnique: ['email','phone']) the 409 body leaked the full record incl. hashedPass.
|
|
54
|
+
*
|
|
55
|
+
* Fix: redact existingRecord to { _id, businessId } like the safe validateUniquenessConstraints
|
|
56
|
+
* path. This reproduces the leak with a same-tenant collision (same code path) and asserts the
|
|
57
|
+
* 409 body's existingRecord exposes nothing beyond _id + businessId.
|
|
58
|
+
*/
|
|
59
|
+
var globalunique_leak_tests = function (_a) {
|
|
60
|
+
var sdk = _a.sdk;
|
|
61
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
62
|
+
var userId, email_1, user, _b;
|
|
63
|
+
return __generator(this, function (_c) {
|
|
64
|
+
switch (_c.label) {
|
|
65
|
+
case 0:
|
|
66
|
+
(0, testing_1.log_header)("F-0145: globalUnique conflict response redaction");
|
|
67
|
+
_c.label = 1;
|
|
68
|
+
case 1:
|
|
69
|
+
_c.trys.push([1, , 4, 9]);
|
|
70
|
+
email_1 = "f0145-victim-".concat(Date.now(), "@example.com");
|
|
71
|
+
return [4 /*yield*/, sdk.api.users.createOne({ email: email_1 })];
|
|
72
|
+
case 2:
|
|
73
|
+
user = _c.sent();
|
|
74
|
+
userId = user.id;
|
|
75
|
+
return [4 /*yield*/, (0, testing_1.async_test)('F-0145: globalUnique 409 existingRecord exposes only _id + businessId (no email/hashedPass)', function () { return sdk.api.users.createOne({ email: email_1, _overrideUnique: true }); }, {
|
|
76
|
+
shouldError: true,
|
|
77
|
+
onError: function (e) {
|
|
78
|
+
var _a, _b;
|
|
79
|
+
var rec = (_b = (_a = e === null || e === void 0 ? void 0 : e.info) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.existingRecord;
|
|
80
|
+
if (!rec || typeof rec !== 'object')
|
|
81
|
+
return false;
|
|
82
|
+
var keys = Object.keys(rec);
|
|
83
|
+
return (keys.length > 0
|
|
84
|
+
&& keys.every(function (k) { return k === '_id' || k === 'businessId' || k === 'id'; })
|
|
85
|
+
&& !('email' in rec)
|
|
86
|
+
&& !('hashedPass' in rec)
|
|
87
|
+
&& !('hashedInviteCode' in rec));
|
|
88
|
+
},
|
|
89
|
+
})];
|
|
90
|
+
case 3:
|
|
91
|
+
_c.sent();
|
|
92
|
+
return [3 /*break*/, 9];
|
|
93
|
+
case 4:
|
|
94
|
+
if (!userId) return [3 /*break*/, 8];
|
|
95
|
+
_c.label = 5;
|
|
96
|
+
case 5:
|
|
97
|
+
_c.trys.push([5, 7, , 8]);
|
|
98
|
+
return [4 /*yield*/, sdk.api.users.deleteOne(userId)];
|
|
99
|
+
case 6:
|
|
100
|
+
_c.sent();
|
|
101
|
+
return [3 /*break*/, 8];
|
|
102
|
+
case 7:
|
|
103
|
+
_b = _c.sent();
|
|
104
|
+
return [3 /*break*/, 8];
|
|
105
|
+
case 8: return [7 /*endfinally*/];
|
|
106
|
+
case 9: return [2 /*return*/];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
exports.globalunique_leak_tests = globalunique_leak_tests;
|
|
112
|
+
if (require.main === module) {
|
|
113
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
114
|
+
var sdk_2 = new sdk_1.Session({ host: host });
|
|
115
|
+
var sdkNonAdmin_1 = new sdk_1.Session({ host: host });
|
|
116
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
117
|
+
return __generator(this, function (_a) {
|
|
118
|
+
switch (_a.label) {
|
|
119
|
+
case 0: return [4 /*yield*/, (0, setup_1.setup_tests)(sdk_2, sdkNonAdmin_1)];
|
|
120
|
+
case 1:
|
|
121
|
+
_a.sent();
|
|
122
|
+
return [4 /*yield*/, (0, exports.globalunique_leak_tests)({ sdk: sdk_2, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
123
|
+
case 2:
|
|
124
|
+
_a.sent();
|
|
125
|
+
return [2 /*return*/];
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}); };
|
|
129
|
+
runTests()
|
|
130
|
+
.then(function () {
|
|
131
|
+
console.log("✅ F-0145 globalUnique leak test suite completed successfully");
|
|
132
|
+
process.exit(0);
|
|
133
|
+
})
|
|
134
|
+
.catch(function (error) {
|
|
135
|
+
console.error("❌ F-0145 globalUnique leak test suite failed:", error);
|
|
136
|
+
process.exit(1);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=F-0145-globalunique-leak.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"F-0145-globalunique-leak.test.js","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0145-globalunique-leak.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Session } from "../../../sdk";
|
|
2
|
+
/**
|
|
3
|
+
* Regression test for F-0151
|
|
4
|
+
* (security-audit/findings/F-0151-load-inbox-data-endusers-unredacted.md).
|
|
5
|
+
*
|
|
6
|
+
* load_inbox_data serialized $lookup'ed endusers via convert_id_name only (NOT applyRedactions),
|
|
7
|
+
* so endusers.hashedPassword (redactions:['all']) leaked to staff sessions — while the sibling
|
|
8
|
+
* phone_calls in the same response correctly went through applyRedactions.
|
|
9
|
+
*
|
|
10
|
+
* Repro: create an enduser, set their portal password (→ hashedPassword), seed an inbound
|
|
11
|
+
* (logOnly) email so the enduser appears in the inbox join, then load_inbox_data as staff and
|
|
12
|
+
* assert the returned enduser entry has NO hashedPassword.
|
|
13
|
+
*/
|
|
14
|
+
export declare const load_inbox_redaction_tests: ({ sdk }: {
|
|
15
|
+
sdk: Session;
|
|
16
|
+
sdkNonAdmin: Session;
|
|
17
|
+
}) => Promise<void>;
|
|
18
|
+
//# sourceMappingURL=F-0151-load-inbox-redaction.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"F-0151-load-inbox-redaction.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0151-load-inbox-redaction.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAWtC;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,0BAA0B;SAA2B,OAAO;iBAAe,OAAO;mBAkC9F,CAAA"}
|