@tellescope/sdk 1.253.0 → 1.254.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.
Files changed (98) hide show
  1. package/lib/cjs/sdk.d.ts +4 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/tests/api_tests/_tmp_bc_verify.test.d.ts.map +1 -0
  4. package/lib/cjs/tests/api_tests/_tmp_blank_status_verify.test.d.ts.map +1 -0
  5. package/lib/cjs/tests/api_tests/_tmp_followup_verify.test.d.ts.map +1 -0
  6. package/lib/cjs/tests/api_tests/_tmp_nonmatch_verify.test.d.ts.map +1 -0
  7. package/lib/cjs/tests/api_tests/beluga_manual_sync.test.d.ts +6 -0
  8. package/lib/cjs/tests/api_tests/beluga_manual_sync.test.d.ts.map +1 -0
  9. package/lib/cjs/tests/api_tests/beluga_manual_sync.test.js +256 -0
  10. package/lib/cjs/tests/api_tests/beluga_manual_sync.test.js.map +1 -0
  11. package/lib/cjs/tests/api_tests/field_redaction.test.d.ts.map +1 -1
  12. package/lib/cjs/tests/api_tests/field_redaction.test.js +112 -99
  13. package/lib/cjs/tests/api_tests/field_redaction.test.js.map +1 -1
  14. package/lib/cjs/tests/api_tests/gcal_sync_retry.test.d.ts +43 -0
  15. package/lib/cjs/tests/api_tests/gcal_sync_retry.test.d.ts.map +1 -0
  16. package/lib/cjs/tests/api_tests/gcal_sync_retry.test.js +168 -0
  17. package/lib/cjs/tests/api_tests/gcal_sync_retry.test.js.map +1 -0
  18. package/lib/cjs/tests/api_tests/journey_error_branching.test.js +7 -2
  19. package/lib/cjs/tests/api_tests/journey_error_branching.test.js.map +1 -1
  20. package/lib/cjs/tests/api_tests/resource_access_tags.test.d.ts +22 -0
  21. package/lib/cjs/tests/api_tests/resource_access_tags.test.d.ts.map +1 -0
  22. package/lib/cjs/tests/api_tests/resource_access_tags.test.js +488 -0
  23. package/lib/cjs/tests/api_tests/resource_access_tags.test.js.map +1 -0
  24. package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts +23 -0
  25. package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts.map +1 -0
  26. package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js +325 -0
  27. package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js.map +1 -0
  28. package/lib/cjs/tests/api_tests/time_tracks.test.d.ts +8 -0
  29. package/lib/cjs/tests/api_tests/time_tracks.test.d.ts.map +1 -1
  30. package/lib/cjs/tests/api_tests/time_tracks.test.js +638 -1
  31. package/lib/cjs/tests/api_tests/time_tracks.test.js.map +1 -1
  32. package/lib/cjs/tests/api_tests/user_portal_settings.test.d.ts.map +1 -1
  33. package/lib/cjs/tests/api_tests/user_portal_settings.test.js +104 -28
  34. package/lib/cjs/tests/api_tests/user_portal_settings.test.js.map +1 -1
  35. package/lib/cjs/tests/tests.d.ts.map +1 -1
  36. package/lib/cjs/tests/tests.js +878 -200
  37. package/lib/cjs/tests/tests.js.map +1 -1
  38. package/lib/esm/sdk.d.ts +4 -0
  39. package/lib/esm/sdk.d.ts.map +1 -1
  40. package/lib/esm/tests/api_tests/_tmp_bc_verify.test.d.ts +2 -0
  41. package/lib/esm/tests/api_tests/_tmp_bc_verify.test.d.ts.map +1 -0
  42. package/lib/esm/tests/api_tests/_tmp_bc_verify.test.js +120 -0
  43. package/lib/esm/tests/api_tests/_tmp_bc_verify.test.js.map +1 -0
  44. package/lib/esm/tests/api_tests/_tmp_blank_status_verify.test.d.ts +2 -0
  45. package/lib/esm/tests/api_tests/_tmp_blank_status_verify.test.d.ts.map +1 -0
  46. package/lib/esm/tests/api_tests/_tmp_blank_status_verify.test.js +200 -0
  47. package/lib/esm/tests/api_tests/_tmp_blank_status_verify.test.js.map +1 -0
  48. package/lib/esm/tests/api_tests/_tmp_followup_verify.test.d.ts +2 -0
  49. package/lib/esm/tests/api_tests/_tmp_followup_verify.test.d.ts.map +1 -0
  50. package/lib/esm/tests/api_tests/_tmp_followup_verify.test.js +194 -0
  51. package/lib/esm/tests/api_tests/_tmp_followup_verify.test.js.map +1 -0
  52. package/lib/esm/tests/api_tests/_tmp_nonmatch_verify.test.d.ts +2 -0
  53. package/lib/esm/tests/api_tests/_tmp_nonmatch_verify.test.d.ts.map +1 -0
  54. package/lib/esm/tests/api_tests/_tmp_nonmatch_verify.test.js +115 -0
  55. package/lib/esm/tests/api_tests/_tmp_nonmatch_verify.test.js.map +1 -0
  56. package/lib/esm/tests/api_tests/beluga_manual_sync.test.d.ts +6 -0
  57. package/lib/esm/tests/api_tests/beluga_manual_sync.test.d.ts.map +1 -0
  58. package/lib/esm/tests/api_tests/beluga_manual_sync.test.js +252 -0
  59. package/lib/esm/tests/api_tests/beluga_manual_sync.test.js.map +1 -0
  60. package/lib/esm/tests/api_tests/field_redaction.test.d.ts.map +1 -1
  61. package/lib/esm/tests/api_tests/field_redaction.test.js +112 -99
  62. package/lib/esm/tests/api_tests/field_redaction.test.js.map +1 -1
  63. package/lib/esm/tests/api_tests/gcal_sync_retry.test.d.ts +43 -0
  64. package/lib/esm/tests/api_tests/gcal_sync_retry.test.d.ts.map +1 -0
  65. package/lib/esm/tests/api_tests/gcal_sync_retry.test.js +164 -0
  66. package/lib/esm/tests/api_tests/gcal_sync_retry.test.js.map +1 -0
  67. package/lib/esm/tests/api_tests/journey_error_branching.test.js +7 -2
  68. package/lib/esm/tests/api_tests/journey_error_branching.test.js.map +1 -1
  69. package/lib/esm/tests/api_tests/resource_access_tags.test.d.ts +22 -0
  70. package/lib/esm/tests/api_tests/resource_access_tags.test.d.ts.map +1 -0
  71. package/lib/esm/tests/api_tests/resource_access_tags.test.js +484 -0
  72. package/lib/esm/tests/api_tests/resource_access_tags.test.js.map +1 -0
  73. package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts +23 -0
  74. package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts.map +1 -0
  75. package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js +321 -0
  76. package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js.map +1 -0
  77. package/lib/esm/tests/api_tests/time_tracks.test.d.ts +8 -0
  78. package/lib/esm/tests/api_tests/time_tracks.test.d.ts.map +1 -1
  79. package/lib/esm/tests/api_tests/time_tracks.test.js +635 -0
  80. package/lib/esm/tests/api_tests/time_tracks.test.js.map +1 -1
  81. package/lib/esm/tests/api_tests/user_portal_settings.test.d.ts.map +1 -1
  82. package/lib/esm/tests/api_tests/user_portal_settings.test.js +104 -28
  83. package/lib/esm/tests/api_tests/user_portal_settings.test.js.map +1 -1
  84. package/lib/esm/tests/tests.d.ts.map +1 -1
  85. package/lib/esm/tests/tests.js +879 -201
  86. package/lib/esm/tests/tests.js.map +1 -1
  87. package/lib/tsconfig.tsbuildinfo +1 -1
  88. package/package.json +10 -10
  89. package/src/tests/api_tests/beluga_manual_sync.test.ts +159 -0
  90. package/src/tests/api_tests/field_redaction.test.ts +13 -0
  91. package/src/tests/api_tests/gcal_sync_retry.test.ts +104 -0
  92. package/src/tests/api_tests/journey_error_branching.test.ts +5 -1
  93. package/src/tests/api_tests/resource_access_tags.test.ts +303 -0
  94. package/src/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.ts +214 -0
  95. package/src/tests/api_tests/time_tracks.test.ts +420 -0
  96. package/src/tests/api_tests/user_portal_settings.test.ts +71 -1
  97. package/src/tests/tests.ts +520 -11
  98. package/test_generated.pdf +0 -0
@@ -0,0 +1,484 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
13
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
14
+ return new (P || (P = Promise))(function (resolve, reject) {
15
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
16
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
17
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
18
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
19
+ });
20
+ };
21
+ var __generator = (this && this.__generator) || function (thisArg, body) {
22
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
23
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
24
+ function verb(n) { return function (v) { return step([n, v]); }; }
25
+ function step(op) {
26
+ if (f) throw new TypeError("Generator is already executing.");
27
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
28
+ 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;
29
+ if (y = 0, t) op = [op[0] & 2, t.value];
30
+ switch (op[0]) {
31
+ case 0: case 1: t = op; break;
32
+ case 4: _.label++; return { value: op[1], done: false };
33
+ case 5: _.label++; y = op[1]; op = [0]; continue;
34
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
35
+ default:
36
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
37
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
38
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
39
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
40
+ if (t[2]) _.ops.pop();
41
+ _.trys.pop(); continue;
42
+ }
43
+ op = body.call(thisArg, _);
44
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
45
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
+ }
47
+ };
48
+ require('source-map-support').install();
49
+ import { Session } from "../../sdk";
50
+ import { async_test, handleAnyError, log_header, wait, assert, } from "@tellescope/testing";
51
+ import { PROVIDER_PERMISSIONS } from "@tellescope/constants";
52
+ import { setup_tests } from "../setup";
53
+ var host = process.env.API_URL || 'http://localhost:8080';
54
+ var RAND = function () { return Math.random().toString(36).slice(2, 10); };
55
+ var TAG_A = 'resource-access-tag-A';
56
+ var TAG_B = 'resource-access-tag-B';
57
+ /**
58
+ * Tests for settings.users.enableResourceAccessTags (the `erat` session flag).
59
+ *
60
+ * When the org setting is enabled, org-level configuration resources carrying `accessTags`
61
+ * become visible only to non-admin (Default/Assigned) users whose own tags intersect the
62
+ * record's accessTags. This mirrors the existing enduser accessTags behavior, generalized
63
+ * to the 9 RESOURCE_ACCESS_TAG_MODELS.
64
+ *
65
+ * The model is ADDITIVE: a record only becomes tag-gated once an admin sets accessTags on it.
66
+ * Records without accessTags keep their existing rules (Default == creator-only). Admins and
67
+ * All-access users are unaffected.
68
+ *
69
+ * Per the throwaway-user testing guidance, this test creates throwaway users rather than
70
+ * mutating existing user roles. Tokens are minted via generate_auth_token AFTER the org
71
+ * setting is enabled, so the `erat` flag lands in their sessions.
72
+ */
73
+ export var resource_access_tags_tests = function (_a) {
74
+ var sdk = _a.sdk;
75
+ return __awaiter(void 0, void 0, void 0, function () {
76
+ var DEFAULT_RW, ALL_RW, RESOURCE_MODELS, createdUserIds, createdRoleIds, createdByModel, _i, RESOURCE_MODELS_1, m, helperTemplateId // calendar_event_template used as a booking-page dependency
77
+ , orgId, defaultPermissions, allPermissions, _b, RESOURCE_MODELS_2, m, defaultRole, allRole, rbapDefault, rbapAll, mkUser, _c, sdkWithTag_1, withTagUser, sdkWithoutTag, sdkAllAccess, helperTemplate, createRecord, recordsByModel, _d, RESOURCE_MODELS_3, model, taggedId, untaggedId, visibleIds, _loop_1, _e, RESOURCE_MODELS_4, model, withTagUserId_1, _f, reAuthToken, reAuthUser, sdkWithTagOff, templatesTaggedId_1, offVisible_1, _g, RESOURCE_MODELS_5, model, _h, _j, id, _k, createdRoleIds_1, id, _l, createdUserIds_1, id;
78
+ return __generator(this, function (_m) {
79
+ switch (_m.label) {
80
+ case 0:
81
+ log_header("Resource Access Tags Tests");
82
+ DEFAULT_RW = { create: 'Default', read: 'Default', update: 'Default', delete: 'Default' };
83
+ ALL_RW = { create: 'All', read: 'All', update: 'All', delete: 'All' };
84
+ RESOURCE_MODELS = [
85
+ 'templates', 'forms', 'journeys', 'automation_triggers', 'calendar_event_templates',
86
+ 'appointment_booking_pages', 'table_views', 'files', 'managed_content_records',
87
+ ];
88
+ createdUserIds = [];
89
+ createdRoleIds = [];
90
+ createdByModel = {};
91
+ for (_i = 0, RESOURCE_MODELS_1 = RESOURCE_MODELS; _i < RESOURCE_MODELS_1.length; _i++) {
92
+ m = RESOURCE_MODELS_1[_i];
93
+ createdByModel[m] = [];
94
+ }
95
+ orgId = sdk.userInfo.businessId;
96
+ _m.label = 1;
97
+ case 1:
98
+ _m.trys.push([1, , 25, 42]);
99
+ // ── 1. Enable the org setting ───────────────────────────────────────────────
100
+ // Explicitly disable enduser access tags (eat) so that the tag-edit-restriction
101
+ // assertions below prove the `erat` flag alone enforces the protection (otherwise
102
+ // a residual `eat` could mask the gap). Settings deep-merge, so this is targeted.
103
+ return [4 /*yield*/, sdk.api.organizations.updateOne(orgId, {
104
+ settings: { users: { enableResourceAccessTags: true }, endusers: { enableAccessTags: false } },
105
+ })
106
+ // ── 2. Roles: Default read for a tag-gated user, All read for a control user ──
107
+ ];
108
+ case 2:
109
+ // ── 1. Enable the org setting ───────────────────────────────────────────────
110
+ // Explicitly disable enduser access tags (eat) so that the tag-edit-restriction
111
+ // assertions below prove the `erat` flag alone enforces the protection (otherwise
112
+ // a residual `eat` could mask the gap). Settings deep-merge, so this is targeted.
113
+ _m.sent();
114
+ defaultPermissions = __assign({}, PROVIDER_PERMISSIONS);
115
+ allPermissions = __assign({}, PROVIDER_PERMISSIONS);
116
+ for (_b = 0, RESOURCE_MODELS_2 = RESOURCE_MODELS; _b < RESOURCE_MODELS_2.length; _b++) {
117
+ m = RESOURCE_MODELS_2[_b];
118
+ defaultPermissions[m] = __assign({}, DEFAULT_RW);
119
+ allPermissions[m] = __assign({}, ALL_RW);
120
+ }
121
+ defaultRole = "resource-access-tags-default-".concat(RAND());
122
+ allRole = "resource-access-tags-all-".concat(RAND());
123
+ return [4 /*yield*/, sdk.api.role_based_access_permissions.createOne({ role: defaultRole, permissions: defaultPermissions })];
124
+ case 3:
125
+ rbapDefault = _m.sent();
126
+ return [4 /*yield*/, sdk.api.role_based_access_permissions.createOne({ role: allRole, permissions: allPermissions })];
127
+ case 4:
128
+ rbapAll = _m.sent();
129
+ createdRoleIds.push(rbapDefault.id, rbapAll.id);
130
+ mkUser = function (tags, roles) { return __awaiter(void 0, void 0, void 0, function () {
131
+ var user, _a, authToken, sessionUser, session;
132
+ return __generator(this, function (_b) {
133
+ switch (_b.label) {
134
+ case 0: return [4 /*yield*/, sdk.api.users.createOne({
135
+ email: "resource-access-tags-".concat(RAND(), "@tellescope.example"),
136
+ fname: 'Resource', lname: 'AccessTags',
137
+ notificationEmailsDisabled: true, verifiedEmail: true,
138
+ tags: tags,
139
+ roles: roles,
140
+ })];
141
+ case 1:
142
+ user = _b.sent();
143
+ createdUserIds.push(user.id);
144
+ return [4 /*yield*/, sdk.api.users.generate_auth_token({ id: user.id })];
145
+ case 2:
146
+ _a = _b.sent(), authToken = _a.authToken, sessionUser = _a.user;
147
+ session = new Session({ host: host });
148
+ session.setAuthToken(authToken);
149
+ session.setUserInfo(sessionUser);
150
+ return [2 /*return*/, { session: session, sessionUser: sessionUser }];
151
+ }
152
+ });
153
+ }); };
154
+ return [4 /*yield*/, mkUser([TAG_A], [defaultRole])]; // Default access, carries the gating tag
155
+ case 5:
156
+ _c = _m.sent() // Default access, carries the gating tag
157
+ , sdkWithTag_1 = _c.session, withTagUser = _c.sessionUser;
158
+ return [4 /*yield*/, mkUser([TAG_B], [defaultRole])]; // Default access, lacks the gating tag
159
+ case 6:
160
+ sdkWithoutTag = (_m.sent()) // Default access, lacks the gating tag
161
+ .session;
162
+ return [4 /*yield*/, mkUser([TAG_B], [allRole])
163
+ // sanity check: erat made it into the gated sessions
164
+ ]; // All access, lacks the tag (should still see everything)
165
+ case 7:
166
+ sdkAllAccess = (_m.sent()) // All access, lacks the tag (should still see everything)
167
+ .session;
168
+ // sanity check: erat made it into the gated sessions
169
+ assert(!!withTagUser.erat, 'erat flag missing on tagged user session', 'erat flag present on tagged user session');
170
+ return [4 /*yield*/, sdk.api.calendar_event_templates.createOne({ title: "RAT helper ".concat(RAND()), durationInMinutes: 30 })];
171
+ case 8:
172
+ helperTemplate = _m.sent();
173
+ helperTemplateId = helperTemplate.id;
174
+ createdByModel['calendar_event_templates'].push(helperTemplate.id);
175
+ createRecord = function (model, accessTags) { return __awaiter(void 0, void 0, void 0, function () {
176
+ var tags, id, _a, r, r, r, r, r, r, r, file, r;
177
+ return __generator(this, function (_b) {
178
+ switch (_b.label) {
179
+ case 0:
180
+ tags = accessTags ? { accessTags: accessTags } : {};
181
+ _a = model;
182
+ switch (_a) {
183
+ case 'templates': return [3 /*break*/, 1];
184
+ case 'forms': return [3 /*break*/, 3];
185
+ case 'journeys': return [3 /*break*/, 5];
186
+ case 'automation_triggers': return [3 /*break*/, 7];
187
+ case 'calendar_event_templates': return [3 /*break*/, 9];
188
+ case 'appointment_booking_pages': return [3 /*break*/, 11];
189
+ case 'table_views': return [3 /*break*/, 13];
190
+ case 'files': return [3 /*break*/, 15];
191
+ case 'managed_content_records': return [3 /*break*/, 19];
192
+ }
193
+ return [3 /*break*/, 21];
194
+ case 1: return [4 /*yield*/, sdk.api.templates.createOne(__assign({ title: "RAT tmpl ".concat(RAND()), subject: 's', html: '<p>x</p>', message: 'm' }, tags))];
195
+ case 2:
196
+ r = _b.sent();
197
+ id = r.id;
198
+ return [3 /*break*/, 22];
199
+ case 3: return [4 /*yield*/, sdk.api.forms.createOne(__assign({ title: "RAT form ".concat(RAND()) }, tags))];
200
+ case 4:
201
+ r = _b.sent();
202
+ id = r.id;
203
+ return [3 /*break*/, 22];
204
+ case 5: return [4 /*yield*/, sdk.api.journeys.createOne(__assign({ title: "RAT jrn ".concat(RAND()) }, tags))];
205
+ case 6:
206
+ r = _b.sent();
207
+ id = r.id;
208
+ return [3 /*break*/, 22];
209
+ case 7: return [4 /*yield*/, sdk.api.automation_triggers.createOne(__assign({ title: "RAT trg ".concat(RAND()), status: 'Active', event: { type: 'Appointment Completed', info: {} }, action: { type: 'Add Tags', info: { tags: ['x'] } } }, tags))];
210
+ case 8:
211
+ r = _b.sent();
212
+ id = r.id;
213
+ return [3 /*break*/, 22];
214
+ case 9: return [4 /*yield*/, sdk.api.calendar_event_templates.createOne(__assign({ title: "RAT cet ".concat(RAND()), durationInMinutes: 30 }, tags))];
215
+ case 10:
216
+ r = _b.sent();
217
+ id = r.id;
218
+ return [3 /*break*/, 22];
219
+ case 11: return [4 /*yield*/, sdk.api.appointment_booking_pages.createOne(__assign({ title: "RAT bp ".concat(RAND()), calendarEventTemplateIds: [helperTemplateId], locationIds: [] }, tags))];
220
+ case 12:
221
+ r = _b.sent();
222
+ id = r.id;
223
+ return [3 /*break*/, 22];
224
+ case 13: return [4 /*yield*/, sdk.api.table_views.createOne(__assign({ title: "RAT view ".concat(RAND()), page: 'Ticket', columns: [] }, tags))];
225
+ case 14:
226
+ r = _b.sent();
227
+ id = r.id;
228
+ return [3 /*break*/, 22];
229
+ case 15: return [4 /*yield*/, sdk.api.files.prepare_file_upload({ name: "RAT file ".concat(RAND()), type: 'text/plain', size: 1 })];
230
+ case 16:
231
+ file = (_b.sent()).file;
232
+ if (!accessTags) return [3 /*break*/, 18];
233
+ return [4 /*yield*/, sdk.api.files.updateOne(file.id, { accessTags: accessTags })];
234
+ case 17:
235
+ _b.sent();
236
+ _b.label = 18;
237
+ case 18:
238
+ id = file.id;
239
+ return [3 /*break*/, 22];
240
+ case 19: return [4 /*yield*/, sdk.api.managed_content_records.createOne(__assign({ title: "RAT content ".concat(RAND()), textContent: 't' }, tags))];
241
+ case 20:
242
+ r = _b.sent();
243
+ id = r.id;
244
+ return [3 /*break*/, 22];
245
+ case 21: throw new Error("unhandled model ".concat(model));
246
+ case 22:
247
+ createdByModel[model].push(id);
248
+ return [2 /*return*/, id];
249
+ }
250
+ });
251
+ }); };
252
+ recordsByModel = {};
253
+ _d = 0, RESOURCE_MODELS_3 = RESOURCE_MODELS;
254
+ _m.label = 9;
255
+ case 9:
256
+ if (!(_d < RESOURCE_MODELS_3.length)) return [3 /*break*/, 13];
257
+ model = RESOURCE_MODELS_3[_d];
258
+ return [4 /*yield*/, createRecord(model, [TAG_A])];
259
+ case 10:
260
+ taggedId = _m.sent();
261
+ return [4 /*yield*/, createRecord(model)];
262
+ case 11:
263
+ untaggedId = _m.sent();
264
+ recordsByModel[model] = { taggedId: taggedId, untaggedId: untaggedId };
265
+ _m.label = 12;
266
+ case 12:
267
+ _d++;
268
+ return [3 /*break*/, 9];
269
+ case 13:
270
+ visibleIds = function (session, model, ids) { return __awaiter(void 0, void 0, void 0, function () {
271
+ var records;
272
+ return __generator(this, function (_a) {
273
+ switch (_a.label) {
274
+ case 0: return [4 /*yield*/, session.api[model].getSome({ ids: ids, limit: 100 })];
275
+ case 1:
276
+ records = _a.sent();
277
+ return [2 /*return*/, new Set(records.map(function (r) { return r.id; }))];
278
+ }
279
+ });
280
+ }); };
281
+ _loop_1 = function (model) {
282
+ var _o, taggedId, untaggedId, ids, withTag, withoutTag, admin, allAccess;
283
+ return __generator(this, function (_p) {
284
+ switch (_p.label) {
285
+ case 0:
286
+ _o = recordsByModel[model], taggedId = _o.taggedId, untaggedId = _o.untaggedId;
287
+ ids = [taggedId, untaggedId];
288
+ return [4 /*yield*/, visibleIds(sdkWithTag_1, model, ids)];
289
+ case 1:
290
+ withTag = _p.sent();
291
+ return [4 /*yield*/, visibleIds(sdkWithoutTag, model, ids)];
292
+ case 2:
293
+ withoutTag = _p.sent();
294
+ return [4 /*yield*/, visibleIds(sdk, model, ids)];
295
+ case 3:
296
+ admin = _p.sent();
297
+ return [4 /*yield*/, visibleIds(sdkAllAccess, model, ids)];
298
+ case 4:
299
+ allAccess = _p.sent();
300
+ return [4 /*yield*/, async_test("".concat(model, ": user WITH matching tag CAN read the tagged record"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
301
+ return [2 /*return*/, withTag.has(taggedId)];
302
+ }); }); }, { onResult: function (r) { return r === true; } })];
303
+ case 5:
304
+ _p.sent();
305
+ return [4 /*yield*/, async_test("".concat(model, ": user WITHOUT matching tag CANNOT read the tagged record"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
306
+ return [2 /*return*/, withoutTag.has(taggedId)];
307
+ }); }); }, { onResult: function (r) { return r === false; } })];
308
+ case 6:
309
+ _p.sent();
310
+ return [4 /*yield*/, async_test("".concat(model, ": untagged admin record NOT visible to tagged user (additive model)"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
311
+ return [2 /*return*/, withTag.has(untaggedId)];
312
+ }); }); }, { onResult: function (r) { return r === false; } })];
313
+ case 7:
314
+ _p.sent();
315
+ return [4 /*yield*/, async_test("".concat(model, ": untagged admin record NOT visible to untagged user (additive model)"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
316
+ return [2 /*return*/, withoutTag.has(untaggedId)];
317
+ }); }); }, { onResult: function (r) { return r === false; } })];
318
+ case 8:
319
+ _p.sent();
320
+ return [4 /*yield*/, async_test("".concat(model, ": admin sees both records (gating does not apply)"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
321
+ return [2 /*return*/, admin.has(taggedId) && admin.has(untaggedId)];
322
+ }); }); }, { onResult: function (r) { return r === true; } })];
323
+ case 9:
324
+ _p.sent();
325
+ return [4 /*yield*/, async_test("".concat(model, ": All-access user sees both records (gating does not apply)"), function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
326
+ return [2 /*return*/, allAccess.has(taggedId) && allAccess.has(untaggedId)];
327
+ }); }); }, { onResult: function (r) { return r === true; } })];
328
+ case 10:
329
+ _p.sent();
330
+ return [2 /*return*/];
331
+ }
332
+ });
333
+ };
334
+ _e = 0, RESOURCE_MODELS_4 = RESOURCE_MODELS;
335
+ _m.label = 14;
336
+ case 14:
337
+ if (!(_e < RESOURCE_MODELS_4.length)) return [3 /*break*/, 17];
338
+ model = RESOURCE_MODELS_4[_e];
339
+ return [5 /*yield**/, _loop_1(model)];
340
+ case 15:
341
+ _m.sent();
342
+ _m.label = 16;
343
+ case 16:
344
+ _e++;
345
+ return [3 /*break*/, 14];
346
+ case 17:
347
+ // ── 5b. Tag-edit restriction: a non-admin cannot edit tags to self-escalate ──
348
+ // With erat ON and eat OFF, the users.tags edit guard must still fire — proving
349
+ // resource access tags (not just enduser access tags) trigger the protection.
350
+ log_header("Resource Access Tags: tag-edit blocked");
351
+ withTagUserId_1 = createdUserIds[0];
352
+ return [4 /*yield*/, async_test("non-admin can't update own tags (erat enabled)", function () { return sdkWithTag_1.api.users.updateOne(withTagUserId_1, { tags: ['escalate'] }); }, handleAnyError)];
353
+ case 18:
354
+ _m.sent();
355
+ return [4 /*yield*/, async_test("non-admin can't update own tags alongside other fields (erat enabled)", function () { return sdkWithTag_1.api.users.updateOne(withTagUserId_1, { tags: ['escalate'], bio: '' }); }, handleAnyError)];
356
+ case 19:
357
+ _m.sent();
358
+ return [4 /*yield*/, async_test("non-admin can still update non-tag fields (control)", function () { return sdkWithTag_1.api.users.updateOne(withTagUserId_1, { bio: '' }); }, { shouldError: false, onResult: function () { return true; } })
359
+ // ── 6. Org-setting-OFF control: disabling the flag gates the whole feature ────
360
+ ];
361
+ case 20:
362
+ _m.sent();
363
+ // ── 6. Org-setting-OFF control: disabling the flag gates the whole feature ────
364
+ log_header("Resource Access Tags: org-setting-OFF control");
365
+ return [4 /*yield*/, sdk.api.organizations.updateOne(orgId, {
366
+ settings: { users: { enableResourceAccessTags: false } },
367
+ })
368
+ // re-mint the tagged user's token so the (now-disabled) setting is reflected in the session
369
+ ];
370
+ case 21:
371
+ _m.sent();
372
+ return [4 /*yield*/, sdk.api.users.generate_auth_token({ id: createdUserIds[0] })];
373
+ case 22:
374
+ _f = _m.sent(), reAuthToken = _f.authToken, reAuthUser = _f.user;
375
+ sdkWithTagOff = new Session({ host: host });
376
+ sdkWithTagOff.setAuthToken(reAuthToken);
377
+ sdkWithTagOff.setUserInfo(reAuthUser);
378
+ assert(!reAuthUser.erat, 'erat flag should be absent after disabling setting', 'erat flag absent after disabling setting');
379
+ templatesTaggedId_1 = recordsByModel['templates'].taggedId;
380
+ return [4 /*yield*/, visibleIds(sdkWithTagOff, 'templates', [templatesTaggedId_1])];
381
+ case 23:
382
+ offVisible_1 = _m.sent();
383
+ return [4 /*yield*/, async_test("templates: tagged record NOT visible to tagged user once setting is OFF", function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
384
+ return [2 /*return*/, offVisible_1.has(templatesTaggedId_1)];
385
+ }); }); }, { onResult: function (r) { return r === false; } })];
386
+ case 24:
387
+ _m.sent();
388
+ console.log("\n" + "=".repeat(60));
389
+ console.log("Resource Access Tags Tests Complete");
390
+ console.log("=".repeat(60));
391
+ return [3 /*break*/, 42];
392
+ case 25:
393
+ _g = 0, RESOURCE_MODELS_5 = RESOURCE_MODELS;
394
+ _m.label = 26;
395
+ case 26:
396
+ if (!(_g < RESOURCE_MODELS_5.length)) return [3 /*break*/, 31];
397
+ model = RESOURCE_MODELS_5[_g];
398
+ _h = 0, _j = createdByModel[model];
399
+ _m.label = 27;
400
+ case 27:
401
+ if (!(_h < _j.length)) return [3 /*break*/, 30];
402
+ id = _j[_h];
403
+ return [4 /*yield*/, sdk.api[model].deleteOne(id).catch(function () { })];
404
+ case 28:
405
+ _m.sent();
406
+ _m.label = 29;
407
+ case 29:
408
+ _h++;
409
+ return [3 /*break*/, 27];
410
+ case 30:
411
+ _g++;
412
+ return [3 /*break*/, 26];
413
+ case 31:
414
+ _k = 0, createdRoleIds_1 = createdRoleIds;
415
+ _m.label = 32;
416
+ case 32:
417
+ if (!(_k < createdRoleIds_1.length)) return [3 /*break*/, 35];
418
+ id = createdRoleIds_1[_k];
419
+ return [4 /*yield*/, sdk.api.role_based_access_permissions.deleteOne(id).catch(function () { })];
420
+ case 33:
421
+ _m.sent();
422
+ _m.label = 34;
423
+ case 34:
424
+ _k++;
425
+ return [3 /*break*/, 32];
426
+ case 35:
427
+ _l = 0, createdUserIds_1 = createdUserIds;
428
+ _m.label = 36;
429
+ case 36:
430
+ if (!(_l < createdUserIds_1.length)) return [3 /*break*/, 39];
431
+ id = createdUserIds_1[_l];
432
+ return [4 /*yield*/, sdk.api.users.deleteOne(id).catch(function () { })];
433
+ case 37:
434
+ _m.sent();
435
+ _m.label = 38;
436
+ case 38:
437
+ _l++;
438
+ return [3 /*break*/, 36];
439
+ case 39:
440
+ // reset the org setting
441
+ return [4 /*yield*/, sdk.api.organizations.updateOne(orgId, {
442
+ settings: { users: { enableResourceAccessTags: false } },
443
+ }).catch(function () { })];
444
+ case 40:
445
+ // reset the org setting
446
+ _m.sent();
447
+ return [4 /*yield*/, wait(undefined, 250)];
448
+ case 41:
449
+ _m.sent();
450
+ return [7 /*endfinally*/];
451
+ case 42: return [2 /*return*/];
452
+ }
453
+ });
454
+ });
455
+ };
456
+ // Allow running this test file independently
457
+ if (require.main === module) {
458
+ console.log("\uD83C\uDF10 Using API URL: ".concat(host));
459
+ var sdk_1 = new Session({ host: host });
460
+ var sdkNonAdmin_1 = new Session({ host: host });
461
+ var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
462
+ return __generator(this, function (_a) {
463
+ switch (_a.label) {
464
+ case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
465
+ case 1:
466
+ _a.sent();
467
+ return [4 /*yield*/, resource_access_tags_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
468
+ case 2:
469
+ _a.sent();
470
+ return [2 /*return*/];
471
+ }
472
+ });
473
+ }); };
474
+ runTests()
475
+ .then(function () {
476
+ console.log("✅ Resource access tags test suite completed successfully");
477
+ process.exit(0);
478
+ })
479
+ .catch(function (error) {
480
+ console.error("❌ Resource access tags test suite failed:", error);
481
+ process.exit(1);
482
+ });
483
+ }
484
+ //# sourceMappingURL=resource_access_tags.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource_access_tags.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/resource_access_tags.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import { Session } from "../../../sdk";
2
+ /**
3
+ * Regression test for F-0106 and F-0110
4
+ * (security-audit/findings/F-0106-enduser-self-update-admin-only-fields.md,
5
+ * security-audit/findings/F-0110-form-responses-enduser-update-admin-only-fields.md).
6
+ *
7
+ * Endusers could PATCH admin-only / access-bearing / attribution-bearing fields on
8
+ * their own endusers record (assignedTo, tags, references, ...) and their own
9
+ * form_responses (procedureCodes, submittedBy, markedAsSubmitted, ...). The fix adds
10
+ * the `enduserUpdatesDisabled` field option (schema.ts ModelFieldInfo), enforced for
11
+ * enduser sessions in the generic update handler (routing.ts createDefaultEndpoints).
12
+ *
13
+ * This test asserts, for every flagged field on both models:
14
+ * - an enduser session updating its OWN record gets a 400 "<field> cannot be updated by endusers"
15
+ * - nothing persists (spot-checked on assignedTo, the highest-impact field)
16
+ * - enduser self-updates of allowed fields still work (fname, hideFromEnduserPortal)
17
+ * - staff sessions can still update the restricted fields
18
+ */
19
+ export declare const enduser_write_restrictions_tests: ({ sdk }: {
20
+ sdk: Session;
21
+ sdkNonAdmin: Session;
22
+ }) => Promise<void>;
23
+ //# sourceMappingURL=F-0106-F-0110-enduser-write-restrictions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"F-0106-F-0110-enduser-write-restrictions.test.d.ts","sourceRoot":"","sources":["../../../../../src/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAkB,MAAM,cAAc,CAAA;AA+DtD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,gCAAgC;SAA2B,OAAO;iBAAe,OAAO;mBA6GpG,CAAA"}