@tellescope/schema 1.250.2 → 1.251.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/schema.d.ts +13 -1
- package/lib/cjs/schema.d.ts.map +1 -1
- package/lib/cjs/schema.js +126 -4
- package/lib/cjs/schema.js.map +1 -1
- package/lib/esm/schema.d.ts +13 -1
- package/lib/esm/schema.d.ts.map +1 -1
- package/lib/esm/schema.js +127 -5
- package/lib/esm/schema.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -9
- package/src/schema.ts +127 -3
package/src/schema.ts
CHANGED
|
@@ -90,7 +90,11 @@ import {
|
|
|
90
90
|
AutomationAction,
|
|
91
91
|
TimeTrackTimestamp,
|
|
92
92
|
BelugaPharmacyMapping,
|
|
93
|
+
BelugaAutomationMappingEntry,
|
|
94
|
+
BelugaUpdateVisitPatientPreferenceItem,
|
|
93
95
|
TimeTrack,
|
|
96
|
+
LinkedAccount,
|
|
97
|
+
LinkedAccountAccessEntry,
|
|
94
98
|
} from "@tellescope/types-models"
|
|
95
99
|
|
|
96
100
|
import {
|
|
@@ -261,6 +265,7 @@ import {
|
|
|
261
265
|
exactMatchValidator,
|
|
262
266
|
exactMatchValidatorOptional,
|
|
263
267
|
listOfMongoIdStringValidatorOptionalOrEmptyOk,
|
|
268
|
+
linkedAccountAccessValidator,
|
|
264
269
|
listOfStringsValidatorOptionalOrEmptyOk,
|
|
265
270
|
stringValidatorOptionalEmptyOkay,
|
|
266
271
|
analyticsQueryResultsValidator,
|
|
@@ -934,6 +939,9 @@ export type CustomActions = {
|
|
|
934
939
|
consent: CustomAction<{ termsVersion: string, }, { user: User, authToken: string }>,
|
|
935
940
|
get_users_for_groups: CustomAction<{ groups: string[] }, { userIds: string[] }>,
|
|
936
941
|
play_phone_message: CustomAction<{ userId: string, message: string, enduserId?: string, journeyContext?: JourneyContext }, { }>,
|
|
942
|
+
get_linked_accounts: CustomAction<{}, { linkedAccounts: LinkedAccount[] }>,
|
|
943
|
+
switch_account: CustomAction<{ targetUserId: string }, { authToken: string, user: User }>,
|
|
944
|
+
request_linked_account_access: CustomAction<{ targetEmail: string }, { }>,
|
|
937
945
|
},
|
|
938
946
|
chat_rooms: {
|
|
939
947
|
join_room: CustomAction<{ id: string }, { room: ChatRoom }>,
|
|
@@ -3558,7 +3566,73 @@ export const schema: SchemaV1 = build_schema({
|
|
|
3558
3566
|
|
|
3559
3567
|
return "User organizationIds are readonly"
|
|
3560
3568
|
}
|
|
3561
|
-
}
|
|
3569
|
+
},
|
|
3570
|
+
{
|
|
3571
|
+
explanation: "linkedAccountAccess mutations are constrained to the owner with allowlisted transitions",
|
|
3572
|
+
evaluate: (record, _, session, method, { updates, original }) => {
|
|
3573
|
+
if (!updates || !('linkedAccountAccess' in updates)) return
|
|
3574
|
+
if (method === 'create') {
|
|
3575
|
+
if (updates.linkedAccountAccess && (updates.linkedAccountAccess as any[]).length > 0) {
|
|
3576
|
+
return "linkedAccountAccess cannot be set on user creation"
|
|
3577
|
+
}
|
|
3578
|
+
return
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
// Grant management is reserved to the actor's own session. From a switched session
|
|
3582
|
+
// (session.actorUserId set), even targeting the proxy identity's own record is rejected —
|
|
3583
|
+
// otherwise A-as-B could self-approve other pending requests on B, or delete B's existing
|
|
3584
|
+
// grants and silently revoke other grantees.
|
|
3585
|
+
if ((session as any).actorUserId) {
|
|
3586
|
+
return "Cannot update linkedAccountAccess from a switched session"
|
|
3587
|
+
}
|
|
3588
|
+
|
|
3589
|
+
// self-update only — record carries the post-merge updated document; original is the prior state.
|
|
3590
|
+
const ownerId = (record as any)._id?.toString() ?? (original as any)?._id?.toString() ?? (original as any)?.id
|
|
3591
|
+
if (!(ownerId && ownerId === session.id)) {
|
|
3592
|
+
return "Only the account owner can update linkedAccountAccess"
|
|
3593
|
+
}
|
|
3594
|
+
|
|
3595
|
+
const oldEntries: LinkedAccountAccessEntry[] = (original as any)?.linkedAccountAccess ?? []
|
|
3596
|
+
const newEntries: LinkedAccountAccessEntry[] = (updates.linkedAccountAccess as any) ?? []
|
|
3597
|
+
|
|
3598
|
+
for (const newEntry of newEntries) {
|
|
3599
|
+
const oldMatch = oldEntries.find(e => e.userId === newEntry.userId)
|
|
3600
|
+
if (!oldMatch) {
|
|
3601
|
+
return "Cannot add entries to linkedAccountAccess via direct update; use request_linked_account_access"
|
|
3602
|
+
}
|
|
3603
|
+
|
|
3604
|
+
if (newEntry.email !== oldMatch.email) return "linkedAccountAccess entry email is immutable"
|
|
3605
|
+
if ((newEntry.fname ?? null) !== (oldMatch.fname ?? null)) return "linkedAccountAccess entry fname is immutable"
|
|
3606
|
+
if ((newEntry.lname ?? null) !== (oldMatch.lname ?? null)) return "linkedAccountAccess entry lname is immutable"
|
|
3607
|
+
if ((newEntry.orgName ?? null) !== (oldMatch.orgName ?? null)) return "linkedAccountAccess entry orgName is immutable"
|
|
3608
|
+
if (new Date(newEntry.createdAt).getTime() !== new Date(oldMatch.createdAt).getTime()) return "linkedAccountAccess entry createdAt is immutable"
|
|
3609
|
+
if (new Date(newEntry.requestExpiresAt).getTime() !== new Date(oldMatch.requestExpiresAt).getTime()) return "linkedAccountAccess entry requestExpiresAt is immutable"
|
|
3610
|
+
|
|
3611
|
+
if (newEntry.status !== oldMatch.status) {
|
|
3612
|
+
if (!(oldMatch.status === 'pending' && newEntry.status === 'accepted')) {
|
|
3613
|
+
return "linkedAccountAccess status can only transition from pending to accepted"
|
|
3614
|
+
}
|
|
3615
|
+
// Reject approval of an expired pending request — owner must wait for the requester
|
|
3616
|
+
// to re-issue. requestExpiresAt is immutable per the rule above; the only way for a
|
|
3617
|
+
// pending entry to refresh is request_linked_account_access replacing the expired entry.
|
|
3618
|
+
if (new Date(oldMatch.requestExpiresAt).getTime() < Date.now()) {
|
|
3619
|
+
return "linkedAccountAccess request has expired and cannot be approved; requester must re-request"
|
|
3620
|
+
}
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
return
|
|
3625
|
+
}
|
|
3626
|
+
},
|
|
3627
|
+
{
|
|
3628
|
+
explanation: "Legacy accountAccessGrantedTo field is no longer accepted",
|
|
3629
|
+
evaluate: (_, __, ___, ____, { updates }) => {
|
|
3630
|
+
if (updates && 'accountAccessGrantedTo' in updates) {
|
|
3631
|
+
return "accountAccessGrantedTo has been replaced by linkedAccountAccess"
|
|
3632
|
+
}
|
|
3633
|
+
return
|
|
3634
|
+
}
|
|
3635
|
+
},
|
|
3562
3636
|
],
|
|
3563
3637
|
},
|
|
3564
3638
|
defaultActions: {
|
|
@@ -3731,7 +3805,7 @@ export const schema: SchemaV1 = build_schema({
|
|
|
3731
3805
|
name: 'Play Phone Message',
|
|
3732
3806
|
path: '/users/play-phone-message',
|
|
3733
3807
|
description: "Calls the user and plays a recorded message",
|
|
3734
|
-
parameters: {
|
|
3808
|
+
parameters: {
|
|
3735
3809
|
userId: { validator: mongoIdStringValidator, required: true },
|
|
3736
3810
|
message: { validator: stringValidator5000, required: true },
|
|
3737
3811
|
enduserId: { validator: mongoIdStringValidator },
|
|
@@ -3739,6 +3813,39 @@ export const schema: SchemaV1 = build_schema({
|
|
|
3739
3813
|
},
|
|
3740
3814
|
returns: { },
|
|
3741
3815
|
},
|
|
3816
|
+
get_linked_accounts: {
|
|
3817
|
+
op: "custom", access: 'read', method: "get",
|
|
3818
|
+
name: 'Get Linked Accounts',
|
|
3819
|
+
path: '/users/linked-accounts',
|
|
3820
|
+
description: "Returns accounts that have granted access to the caller",
|
|
3821
|
+
parameters: { },
|
|
3822
|
+
returns: {
|
|
3823
|
+
linkedAccounts: { validator: objectAnyFieldsAnyValuesValidator as any, required: true },
|
|
3824
|
+
},
|
|
3825
|
+
},
|
|
3826
|
+
switch_account: {
|
|
3827
|
+
op: "custom", access: 'update', method: "post",
|
|
3828
|
+
name: 'Switch Account',
|
|
3829
|
+
path: '/users/switch-account',
|
|
3830
|
+
description: "Switches the current session to a target account that has granted access",
|
|
3831
|
+
parameters: {
|
|
3832
|
+
targetUserId: { validator: mongoIdStringRequired, required: true },
|
|
3833
|
+
},
|
|
3834
|
+
returns: {
|
|
3835
|
+
authToken: { validator: stringValidator, required: true },
|
|
3836
|
+
user: { validator: 'user' as any, required: true },
|
|
3837
|
+
},
|
|
3838
|
+
},
|
|
3839
|
+
request_linked_account_access: {
|
|
3840
|
+
op: "custom", access: 'update', method: "post",
|
|
3841
|
+
name: 'Request Linked Account Access',
|
|
3842
|
+
path: '/users/request-linked-account-access',
|
|
3843
|
+
description: "Requests linked-account access from another user identified by email; the target user must accept before the requester can switch into the account",
|
|
3844
|
+
parameters: {
|
|
3845
|
+
targetEmail: { validator: emailValidator, required: true },
|
|
3846
|
+
},
|
|
3847
|
+
returns: { },
|
|
3848
|
+
},
|
|
3742
3849
|
},
|
|
3743
3850
|
publicActions: {
|
|
3744
3851
|
begin_sso: {
|
|
@@ -3852,6 +3959,7 @@ export const schema: SchemaV1 = build_schema({
|
|
|
3852
3959
|
email: {
|
|
3853
3960
|
validator: emailValidator,
|
|
3854
3961
|
required: true,
|
|
3962
|
+
updatesDisabled: true,
|
|
3855
3963
|
examples: ['test@tellescope.com'],
|
|
3856
3964
|
redactions: ['enduser'],
|
|
3857
3965
|
},
|
|
@@ -3978,6 +4086,7 @@ export const schema: SchemaV1 = build_schema({
|
|
|
3978
4086
|
dashboardView: { validator: customDashboardViewValidator },
|
|
3979
4087
|
hideFromCalendarView: { validator: booleanValidator },
|
|
3980
4088
|
requireSSO: { validator: listOfStringsValidatorUniqueOptionalOrEmptyOkay },
|
|
4089
|
+
linkedAccountAccess: { validator: linkedAccountAccessValidator },
|
|
3981
4090
|
}
|
|
3982
4091
|
},
|
|
3983
4092
|
templates: {
|
|
@@ -7170,6 +7279,7 @@ export const schema: SchemaV1 = build_schema({
|
|
|
7170
7279
|
canvasSyncPhoneConsent: { validator: booleanValidator },
|
|
7171
7280
|
canvasStateToLocationId: { validator: objectAnyFieldsValidator(stringValidator100) },
|
|
7172
7281
|
enforceMFA: { validator: booleanValidator },
|
|
7282
|
+
accountSwitchingEnabled: { validator: booleanValidator },
|
|
7173
7283
|
replyToEnduserTransactionalEmails: { validator: emailValidator },
|
|
7174
7284
|
customTermsOfService: { validator: stringValidator },
|
|
7175
7285
|
customPrivacyPolicy: { validator: stringValidator },
|
|
@@ -7225,6 +7335,20 @@ export const schema: SchemaV1 = build_schema({
|
|
|
7225
7335
|
summaryFormId: mongoIdStringOptional,
|
|
7226
7336
|
}))
|
|
7227
7337
|
},
|
|
7338
|
+
belugaAutomationMappings: {
|
|
7339
|
+
validator: listValidatorOptionalOrEmptyOk(objectValidator<BelugaAutomationMappingEntry>({
|
|
7340
|
+
enduserCondition: optionalAnyObjectValidator,
|
|
7341
|
+
patientPreferences: listValidator(objectValidator<BelugaUpdateVisitPatientPreferenceItem>({
|
|
7342
|
+
name: stringValidator,
|
|
7343
|
+
strength: stringValidator,
|
|
7344
|
+
refills: stringValidator,
|
|
7345
|
+
quantity: stringValidator,
|
|
7346
|
+
daysSupply: stringValidator,
|
|
7347
|
+
medId: stringValidator,
|
|
7348
|
+
})),
|
|
7349
|
+
pharmacyId: stringValidator,
|
|
7350
|
+
}))
|
|
7351
|
+
},
|
|
7228
7352
|
},
|
|
7229
7353
|
},
|
|
7230
7354
|
databases: {
|
|
@@ -9734,7 +9858,7 @@ If a voicemail is left, it is indicated by recordingURI, transcription, or recor
|
|
|
9734
9858
|
type: { validator: stringValidator100 }, // only used on creation
|
|
9735
9859
|
maxTokens: { validator: positiveNumberValidator },
|
|
9736
9860
|
conversationId: { validator: mongoIdStringValidator },
|
|
9737
|
-
prompt: { validator:
|
|
9861
|
+
prompt: { validator: stringValidator100000EmptyOkay },
|
|
9738
9862
|
orchestrationId: { validator: stringValidatorOptional }, // optional ID to group multiple conversations as part of the same workflow
|
|
9739
9863
|
},
|
|
9740
9864
|
returns: {
|