evo360-types 1.3.570 → 1.3.574
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/dist/apps/evo-crm/lead/zod-schemas.d.ts +9 -9
- package/dist/apps/evo-csq/zod-schemas.d.ts +12 -12
- package/dist/apps/evo-finops/zod-schemas.d.ts +18 -18
- package/dist/apps/evo-med/dic/zod-schemas.d.ts +2 -2
- package/dist/apps/evo-med/people/zod-schemas.d.ts +45 -45
- package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.d.ts +3 -0
- package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.js +3 -0
- package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.ts +3 -0
- package/dist/apps/evo-notifications/zod-schemas.d.ts +69 -39
- package/dist/apps/evo-task/zod-schemas.d.ts +69 -69
- package/dist/apps/evo-task/zod-schemas.js +8 -0
- package/dist/apps/evo-task/zod-schemas.ts +8 -0
- package/dist/apps/evo-telemedicine/zod-schemas.d.ts +1445 -0
- package/dist/apps/evo-telemedicine/zod-schemas.js +641 -0
- package/dist/apps/evo-telemedicine/zod-schemas.ts +723 -0
- package/dist/apps/evo-tenant/zod-schemas.d.ts +94 -0
- package/dist/apps/evo-tenant/zod-schemas.js +29 -1
- package/dist/apps/evo-tenant/zod-schemas.ts +32 -1
- package/dist/apps/hub-automation/zod-schemas.d.ts +172 -172
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/index.ts +2 -0
- package/dist/types/evo-med/calendar/index.d.ts +6 -0
- package/dist/types/evo-med/calendar/index.js +6 -0
- package/dist/types/evo-med/calendar/index.ts +6 -0
- package/dist/types/evo-notifications/index.d.ts +13 -0
- package/dist/types/evo-notifications/index.js +6 -0
- package/dist/types/evo-notifications/index.ts +13 -0
- package/dist/types/evo-task/index.d.ts +1 -0
- package/dist/types/evo-task/index.js +8 -0
- package/dist/types/evo-task/index.ts +8 -0
- package/dist/types/evo-telemedicine/fb_collections.d.ts +16 -0
- package/dist/types/evo-telemedicine/fb_collections.js +38 -0
- package/dist/types/evo-telemedicine/fb_collections.ts +37 -0
- package/dist/types/evo-telemedicine/index.d.ts +890 -0
- package/dist/types/evo-telemedicine/index.js +361 -0
- package/dist/types/evo-telemedicine/index.ts +1046 -0
- package/dist/types/evo-tenant/index.d.ts +45 -0
- package/dist/types/evo-tenant/index.js +20 -1
- package/dist/types/evo-tenant/index.ts +65 -0
- package/dist/types/shared/external-links.d.ts +6 -0
- package/dist/types/shared/external-links.js +6 -0
- package/dist/types/shared/external-links.ts +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import {
|
|
3
|
+
zFireDocSchema,
|
|
4
|
+
zFirestoreDateSchema,
|
|
5
|
+
} from "../shared/zod-schemas";
|
|
6
|
+
import { zTenantModuleEntitlementSchema } from "../evo-tenant/zod-schemas";
|
|
7
|
+
|
|
8
|
+
// ======================================================
|
|
9
|
+
// evo-telemedicine (feat-160) — zod schemas
|
|
10
|
+
//
|
|
11
|
+
// Espelhos À MÃO dos enums/interfaces em types/evo-telemedicine/index.ts (o
|
|
12
|
+
// repo não gera um lado a partir do outro). Ao acrescentar um valor no `*Enum`
|
|
13
|
+
// TS, acrescente aqui — e vice-versa. Doc schemas usam `.passthrough()` para
|
|
14
|
+
// tolerar campos aditivos sem republish; command schemas são ESTRITOS (fronteira
|
|
15
|
+
// HTTP) e nunca aceitam `tenant` no body.
|
|
16
|
+
// ======================================================
|
|
17
|
+
|
|
18
|
+
// ----- Enums ----------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
/** Espelha `TeleconsultationStatusEnum`. */
|
|
21
|
+
export const zTeleconsultationStatusSchema = z.enum([
|
|
22
|
+
"scheduled",
|
|
23
|
+
"open",
|
|
24
|
+
"live",
|
|
25
|
+
"reconnecting",
|
|
26
|
+
"ending",
|
|
27
|
+
"ended",
|
|
28
|
+
"cancelled",
|
|
29
|
+
"expired",
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
/** Espelha `WaitingPolicyEnum`. */
|
|
33
|
+
export const zWaitingPolicySchema = z.enum([
|
|
34
|
+
"manual_admit",
|
|
35
|
+
"auto_when_doctor_present",
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
/** Espelha `TeleconsultationModeEnum`. */
|
|
39
|
+
export const zTeleconsultationModeSchema = z.enum([
|
|
40
|
+
"audio_video",
|
|
41
|
+
"audio_only_allowed",
|
|
42
|
+
]);
|
|
43
|
+
|
|
44
|
+
/** Espelha `TeleconsultationProviderEnum`. */
|
|
45
|
+
export const zTeleconsultationProviderSchema = z.enum(["realtimekit"]);
|
|
46
|
+
|
|
47
|
+
/** Espelha `ParticipantRoleEnum`. */
|
|
48
|
+
export const zParticipantRoleSchema = z.enum(["doctor", "patient"]);
|
|
49
|
+
|
|
50
|
+
/** Espelha `ParticipantStateEnum`. */
|
|
51
|
+
export const zParticipantStateSchema = z.enum([
|
|
52
|
+
"invited",
|
|
53
|
+
"verified",
|
|
54
|
+
"waiting",
|
|
55
|
+
"connected",
|
|
56
|
+
"disconnected",
|
|
57
|
+
"left",
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/** Espelha `PresenceStateEnum` (subconjunto reportável pelo cliente). */
|
|
61
|
+
export const zPresenceStateSchema = z.enum([
|
|
62
|
+
"waiting",
|
|
63
|
+
"connected",
|
|
64
|
+
"disconnected",
|
|
65
|
+
"left",
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
/** Espelha `IdentityLevelEnum`. */
|
|
69
|
+
export const zIdentityLevelSchema = z.enum(["none", "weak", "strong"]);
|
|
70
|
+
|
|
71
|
+
/** Espelha `RecordingStatusEnum`. */
|
|
72
|
+
export const zRecordingStatusSchema = z.enum([
|
|
73
|
+
"idle",
|
|
74
|
+
"consent_pending",
|
|
75
|
+
"recording",
|
|
76
|
+
"stopping",
|
|
77
|
+
"failed",
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
/** Espelha `TranscriptionStatusEnum`. */
|
|
81
|
+
export const zTranscriptionStatusSchema = z.enum([
|
|
82
|
+
"not_requested",
|
|
83
|
+
"queued",
|
|
84
|
+
"processing",
|
|
85
|
+
"ready",
|
|
86
|
+
"failed",
|
|
87
|
+
"deleted",
|
|
88
|
+
]);
|
|
89
|
+
|
|
90
|
+
/** Espelha `ConsentSubjectEnum`. */
|
|
91
|
+
export const zConsentSubjectSchema = z.enum([
|
|
92
|
+
"terms",
|
|
93
|
+
"privacy",
|
|
94
|
+
"recording",
|
|
95
|
+
"transcription",
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
/** Espelha `ConsentDecisionEnum`. */
|
|
99
|
+
export const zConsentDecisionSchema = z.enum([
|
|
100
|
+
"accepted",
|
|
101
|
+
"declined",
|
|
102
|
+
"withdrawn",
|
|
103
|
+
]);
|
|
104
|
+
|
|
105
|
+
/** Espelha `ConsentActorTypeEnum`. */
|
|
106
|
+
export const zConsentActorTypeSchema = z.enum(["patient", "doctor"]);
|
|
107
|
+
|
|
108
|
+
/** Espelha `ArtifactTypeEnum`. */
|
|
109
|
+
export const zArtifactTypeSchema = z.enum([
|
|
110
|
+
"recording_audio_video",
|
|
111
|
+
"recording_audio",
|
|
112
|
+
"transcript",
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
/** Espelha `ArtifactStatusEnum`. */
|
|
116
|
+
export const zArtifactStatusSchema = z.enum([
|
|
117
|
+
"pending",
|
|
118
|
+
"processing",
|
|
119
|
+
"ready",
|
|
120
|
+
"failed",
|
|
121
|
+
"deleting",
|
|
122
|
+
"deleted",
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
/** Espelha `AccessGrantKindEnum`. */
|
|
126
|
+
export const zAccessGrantKindSchema = z.enum([
|
|
127
|
+
"qr_capability",
|
|
128
|
+
"launch_code",
|
|
129
|
+
"browser_session",
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
/** Espelha `AccessGrantStateEnum`. */
|
|
133
|
+
export const zAccessGrantStateSchema = z.enum([
|
|
134
|
+
"active",
|
|
135
|
+
"consumed",
|
|
136
|
+
"blocked",
|
|
137
|
+
"revoked",
|
|
138
|
+
"expired",
|
|
139
|
+
]);
|
|
140
|
+
|
|
141
|
+
/** Espelha `AccessSendChannelKindEnum`. */
|
|
142
|
+
export const zAccessSendChannelKindSchema = z.enum([
|
|
143
|
+
"whatsapp",
|
|
144
|
+
"email",
|
|
145
|
+
"manual",
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
/** Espelha `EndedByTypeEnum`. */
|
|
149
|
+
export const zEndedByTypeSchema = z.enum(["user", "system"]);
|
|
150
|
+
|
|
151
|
+
/** Espelha `TeleconsultationEventActorTypeEnum`. */
|
|
152
|
+
export const zTeleconsultationEventActorTypeSchema = z.enum([
|
|
153
|
+
"user",
|
|
154
|
+
"patient",
|
|
155
|
+
"system",
|
|
156
|
+
"provider",
|
|
157
|
+
]);
|
|
158
|
+
|
|
159
|
+
/** Espelha `TeleconsultationEventSourceEnum`. */
|
|
160
|
+
export const zTeleconsultationEventSourceSchema = z.enum([
|
|
161
|
+
"api",
|
|
162
|
+
"webhook",
|
|
163
|
+
"appointment_reconciler",
|
|
164
|
+
"retention_job",
|
|
165
|
+
"sweep",
|
|
166
|
+
]);
|
|
167
|
+
|
|
168
|
+
/** Espelha `TeleconsultationEventTypeEnum`. ADITIVO: eventos já gravados dependem desta lista. */
|
|
169
|
+
export const zTeleconsultationEventTypeSchema = z.enum([
|
|
170
|
+
"teleconsultation.created",
|
|
171
|
+
"teleconsultation.rescheduled",
|
|
172
|
+
"teleconsultation.cancelled",
|
|
173
|
+
"teleconsultation.expired",
|
|
174
|
+
"teleconsultation.diverged",
|
|
175
|
+
"access.created",
|
|
176
|
+
"access.revoked",
|
|
177
|
+
"access.exchanged",
|
|
178
|
+
"access.verification_failed",
|
|
179
|
+
"access.blocked",
|
|
180
|
+
"host.claimed",
|
|
181
|
+
"host.reassigned",
|
|
182
|
+
"waiting_policy.changed",
|
|
183
|
+
"doctor.prepared",
|
|
184
|
+
"doctor.joined",
|
|
185
|
+
"doctor.disconnected",
|
|
186
|
+
"doctor.rejoined",
|
|
187
|
+
"doctor.left",
|
|
188
|
+
"patient.verified",
|
|
189
|
+
"patient.waiting",
|
|
190
|
+
"patient.admitted",
|
|
191
|
+
"patient.rejected",
|
|
192
|
+
"patient.joined",
|
|
193
|
+
"patient.disconnected",
|
|
194
|
+
"patient.rejoined",
|
|
195
|
+
"patient.left",
|
|
196
|
+
"recording.consent_requested",
|
|
197
|
+
"recording.consent_accepted",
|
|
198
|
+
"recording.consent_declined",
|
|
199
|
+
"recording.consent_withdrawn",
|
|
200
|
+
"recording.started",
|
|
201
|
+
"recording.stopped",
|
|
202
|
+
"recording.failed",
|
|
203
|
+
"transcription.queued",
|
|
204
|
+
"transcription.ready",
|
|
205
|
+
"transcription.failed",
|
|
206
|
+
"transcription.deleted",
|
|
207
|
+
"consultation.started",
|
|
208
|
+
"consultation.reconnecting",
|
|
209
|
+
"consultation.ended",
|
|
210
|
+
"artifact.accessed",
|
|
211
|
+
"artifact.deleted",
|
|
212
|
+
"entitlement.denied",
|
|
213
|
+
"rollout.denied",
|
|
214
|
+
"permission.denied",
|
|
215
|
+
"webhook.observed",
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
/** Espelha `WebhookEventStatusEnum`. */
|
|
219
|
+
export const zWebhookEventStatusSchema = z.enum([
|
|
220
|
+
"pending",
|
|
221
|
+
"claimed",
|
|
222
|
+
"completed",
|
|
223
|
+
"failed",
|
|
224
|
+
]);
|
|
225
|
+
|
|
226
|
+
/** Espelha `LegalTextStatusEnum`. */
|
|
227
|
+
export const zLegalTextStatusSchema = z.enum(["draft", "published", "retired"]);
|
|
228
|
+
|
|
229
|
+
/** Espelha `TranscriptionProviderEnum`. */
|
|
230
|
+
export const zTranscriptionProviderSchema = z.enum(["none", "realtimekit"]);
|
|
231
|
+
|
|
232
|
+
/** Espelha `EntitlementAuditActionEnum`. */
|
|
233
|
+
export const zEntitlementAuditActionSchema = z.enum(["set", "override", "revoke"]);
|
|
234
|
+
|
|
235
|
+
/** Espelha `TelemedicineErrorCode`. */
|
|
236
|
+
export const zTelemedicineErrorCodeSchema = z.enum([
|
|
237
|
+
"TENANT_MODULE_DISABLED",
|
|
238
|
+
"ROLLOUT_DISABLED",
|
|
239
|
+
"EMERGENCY_KILL",
|
|
240
|
+
"PERMISSION_DENIED",
|
|
241
|
+
"CAPABILITY_DISABLED",
|
|
242
|
+
"NOT_FOUND",
|
|
243
|
+
"ACCESS_WINDOW_CLOSED",
|
|
244
|
+
"HOST_CLAIMED_BY_OTHER",
|
|
245
|
+
"HOST_REQUIRED",
|
|
246
|
+
"CONSENT_REQUIRED",
|
|
247
|
+
"IDENTITY_REQUIRED",
|
|
248
|
+
"IDENTITY_VERIFICATION_FAILED",
|
|
249
|
+
"GRANT_BLOCKED",
|
|
250
|
+
"GRANT_INVALID",
|
|
251
|
+
"SESSION_INVALID",
|
|
252
|
+
"TELECONSULTATION_TERMINAL",
|
|
253
|
+
"INVALID_TRANSITION",
|
|
254
|
+
"VERSION_CONFLICT",
|
|
255
|
+
"WAITING_POLICY_LOCKED",
|
|
256
|
+
"RECORDING_ACTIVE",
|
|
257
|
+
"RECORDING_FAILED",
|
|
258
|
+
"TRANSCRIPTION_GATE_CLOSED",
|
|
259
|
+
"ARTIFACT_NOT_READY",
|
|
260
|
+
"PROVIDER_ERROR",
|
|
261
|
+
"RATE_LIMITED",
|
|
262
|
+
"VALIDATION_ERROR",
|
|
263
|
+
]);
|
|
264
|
+
|
|
265
|
+
// ----- Value objects ----------------------------------------------------------
|
|
266
|
+
|
|
267
|
+
const zDate = zFirestoreDateSchema;
|
|
268
|
+
const zDateNullable = zFirestoreDateSchema.nullable().optional();
|
|
269
|
+
|
|
270
|
+
/** Metadata allowlisted (sem PII/conteúdo médico): só primitivos. */
|
|
271
|
+
export const zTeleconsultationEventMetadataSchema = z.record(
|
|
272
|
+
z.string().min(1).max(60),
|
|
273
|
+
z.union([z.string().max(500), z.number(), z.boolean()])
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
export const zTeleconsultationEndedBySchema = z
|
|
277
|
+
.object({
|
|
278
|
+
type: zEndedByTypeSchema,
|
|
279
|
+
id: z.string().optional(),
|
|
280
|
+
reason: z.string().min(1).max(120),
|
|
281
|
+
})
|
|
282
|
+
.passthrough();
|
|
283
|
+
|
|
284
|
+
export const zTeleconsultationEntitlementSnapshotSchema = z
|
|
285
|
+
.object({
|
|
286
|
+
version: z.number().int().min(0),
|
|
287
|
+
capabilities: z.record(
|
|
288
|
+
z.string(),
|
|
289
|
+
z.union([z.boolean(), z.number(), z.string()])
|
|
290
|
+
),
|
|
291
|
+
})
|
|
292
|
+
.passthrough();
|
|
293
|
+
|
|
294
|
+
export const zTeleconsultationEventActorSchema = z
|
|
295
|
+
.object({
|
|
296
|
+
type: zTeleconsultationEventActorTypeSchema,
|
|
297
|
+
id: z.string().optional(),
|
|
298
|
+
})
|
|
299
|
+
.passthrough();
|
|
300
|
+
|
|
301
|
+
// ----- Documentos (por tenant) -------------------------------------------------
|
|
302
|
+
|
|
303
|
+
/** Espelha `ITeleconsultation`. */
|
|
304
|
+
export const zTeleconsultationSchema = zFireDocSchema
|
|
305
|
+
.extend({
|
|
306
|
+
calendar_id: z.string().min(1),
|
|
307
|
+
appointment_id: z.string().min(1),
|
|
308
|
+
patient_id: z.string().min(1),
|
|
309
|
+
scheduled_professional_id: z.string().optional(),
|
|
310
|
+
claimed_host_user_id: z.string().optional(),
|
|
311
|
+
claimed_host_at: zDateNullable,
|
|
312
|
+
mode: zTeleconsultationModeSchema,
|
|
313
|
+
status: zTeleconsultationStatusSchema,
|
|
314
|
+
waiting_policy: zWaitingPolicySchema,
|
|
315
|
+
scheduled_start_at: zDate,
|
|
316
|
+
scheduled_end_at: zDate,
|
|
317
|
+
doctor_access_from: zDate,
|
|
318
|
+
patient_access_from: zDate,
|
|
319
|
+
unused_expires_at: zDate,
|
|
320
|
+
reconnect_until: zDateNullable,
|
|
321
|
+
started_at: zDateNullable,
|
|
322
|
+
ended_at: zDateNullable,
|
|
323
|
+
ended_by: zTeleconsultationEndedBySchema.nullable().optional(),
|
|
324
|
+
provider: zTeleconsultationProviderSchema,
|
|
325
|
+
provider_meeting_id: z.string().optional(),
|
|
326
|
+
active_provider_session_id: z.string().optional(),
|
|
327
|
+
recording_status: zRecordingStatusSchema,
|
|
328
|
+
transcription_status: zTranscriptionStatusSchema,
|
|
329
|
+
entitlement_snapshot: zTeleconsultationEntitlementSnapshotSchema,
|
|
330
|
+
generation: z.number().int().min(0),
|
|
331
|
+
reschedule_count: z.number().int().min(0).optional(),
|
|
332
|
+
last_reconciled_appointment_version: z
|
|
333
|
+
.union([z.number(), z.string()])
|
|
334
|
+
.nullable()
|
|
335
|
+
.optional(),
|
|
336
|
+
last_reconciled_at: zDateNullable,
|
|
337
|
+
version: z.number().int().min(0),
|
|
338
|
+
})
|
|
339
|
+
.passthrough();
|
|
340
|
+
|
|
341
|
+
/** Espelha `ITeleconsultationParticipant`. */
|
|
342
|
+
export const zTeleconsultationParticipantSchema = zFireDocSchema
|
|
343
|
+
.extend({
|
|
344
|
+
teleconsultation_id: z.string().min(1),
|
|
345
|
+
role: zParticipantRoleSchema,
|
|
346
|
+
actor_user_id: z.string().optional(),
|
|
347
|
+
patient_id: z.string().optional(),
|
|
348
|
+
provider_participant_id: z.string().optional(),
|
|
349
|
+
opaque_custom_participant_id: z.string().min(1),
|
|
350
|
+
state: zParticipantStateSchema,
|
|
351
|
+
identity_level: zIdentityLevelSchema.optional(),
|
|
352
|
+
admitted_at: zDateNullable,
|
|
353
|
+
connected_at: zDateNullable,
|
|
354
|
+
last_seen_at: zDateNullable,
|
|
355
|
+
disconnected_at: zDateNullable,
|
|
356
|
+
reconnect_count: z.number().int().min(0),
|
|
357
|
+
})
|
|
358
|
+
.passthrough();
|
|
359
|
+
|
|
360
|
+
export const zTeleconsultationConsentEvidenceSchema = z
|
|
361
|
+
.object({
|
|
362
|
+
ui_locale: z.string().min(2).max(10),
|
|
363
|
+
session_id_hash: z.string().min(1),
|
|
364
|
+
})
|
|
365
|
+
.passthrough();
|
|
366
|
+
|
|
367
|
+
/** Espelha `ITeleconsultationConsent`. */
|
|
368
|
+
export const zTeleconsultationConsentSchema = zFireDocSchema
|
|
369
|
+
.extend({
|
|
370
|
+
teleconsultation_id: z.string().min(1),
|
|
371
|
+
subject: zConsentSubjectSchema,
|
|
372
|
+
decision: zConsentDecisionSchema,
|
|
373
|
+
terms_version: z.string().min(1).max(40),
|
|
374
|
+
terms_content_hash: z.string().optional(),
|
|
375
|
+
participant_id: z.string().min(1),
|
|
376
|
+
actor_type: zConsentActorTypeSchema,
|
|
377
|
+
occurred_at: zDate,
|
|
378
|
+
correlation_id: z.string().min(1),
|
|
379
|
+
recording_request_id: z.string().optional(),
|
|
380
|
+
evidence: zTeleconsultationConsentEvidenceSchema,
|
|
381
|
+
})
|
|
382
|
+
.passthrough();
|
|
383
|
+
|
|
384
|
+
/** Espelha `ITeleconsultationArtifact`. */
|
|
385
|
+
export const zTeleconsultationArtifactSchema = zFireDocSchema
|
|
386
|
+
.extend({
|
|
387
|
+
teleconsultation_id: z.string().min(1),
|
|
388
|
+
type: zArtifactTypeSchema,
|
|
389
|
+
segment: z.number().int().min(1),
|
|
390
|
+
status: zArtifactStatusSchema,
|
|
391
|
+
provider_artifact_id: z.string().optional(),
|
|
392
|
+
provider_session_id: z.string().optional(),
|
|
393
|
+
recording_request_id: z.string().optional(),
|
|
394
|
+
storage_bucket: z.string().optional(),
|
|
395
|
+
storage_object: z.string().optional(),
|
|
396
|
+
content_type: z.string().optional(),
|
|
397
|
+
size_bytes: z.number().int().min(0).optional(),
|
|
398
|
+
checksum: z.string().optional(),
|
|
399
|
+
started_at: zDateNullable,
|
|
400
|
+
ended_at: zDateNullable,
|
|
401
|
+
expires_at: zDateNullable,
|
|
402
|
+
error_code: z.string().optional(),
|
|
403
|
+
})
|
|
404
|
+
.passthrough();
|
|
405
|
+
|
|
406
|
+
/** Espelha `ITeleconsultationEvent` (append-only). */
|
|
407
|
+
export const zTeleconsultationEventSchema = zFireDocSchema
|
|
408
|
+
.extend({
|
|
409
|
+
teleconsultation_id: z.string().min(1),
|
|
410
|
+
type: zTeleconsultationEventTypeSchema,
|
|
411
|
+
occurred_at: zDate,
|
|
412
|
+
actor: zTeleconsultationEventActorSchema,
|
|
413
|
+
source: zTeleconsultationEventSourceSchema,
|
|
414
|
+
correlation_id: z.string().min(1),
|
|
415
|
+
causation_id: z.string().optional(),
|
|
416
|
+
idempotency_key: z.string().optional(),
|
|
417
|
+
from_status: z.string().optional(),
|
|
418
|
+
to_status: z.string().optional(),
|
|
419
|
+
metadata: zTeleconsultationEventMetadataSchema.optional(),
|
|
420
|
+
})
|
|
421
|
+
.passthrough();
|
|
422
|
+
|
|
423
|
+
/** Espelha `ITeleconsultationWebhookEvent` (dedup + outbox). */
|
|
424
|
+
export const zTeleconsultationWebhookEventSchema = zFireDocSchema
|
|
425
|
+
.extend({
|
|
426
|
+
teleconsultation_id: z.string().optional(),
|
|
427
|
+
provider: zTeleconsultationProviderSchema,
|
|
428
|
+
provider_event_id: z.string().min(1),
|
|
429
|
+
event_type: z.string().min(1),
|
|
430
|
+
payload_hash: z.string().optional(),
|
|
431
|
+
sanitized_payload: z
|
|
432
|
+
.record(
|
|
433
|
+
z.string(),
|
|
434
|
+
z.union([z.string(), z.number(), z.boolean(), z.null()])
|
|
435
|
+
)
|
|
436
|
+
.optional(),
|
|
437
|
+
status: zWebhookEventStatusSchema,
|
|
438
|
+
received_at: zDate,
|
|
439
|
+
claimed_at: zDateNullable,
|
|
440
|
+
claimed_by: z.string().optional(),
|
|
441
|
+
lease_until: zDateNullable,
|
|
442
|
+
processed_at: zDateNullable,
|
|
443
|
+
attempt: z.number().int().min(0),
|
|
444
|
+
next_attempt_at: zDateNullable,
|
|
445
|
+
result: z.string().optional(),
|
|
446
|
+
error_code: z.string().optional(),
|
|
447
|
+
correlation_id: z.string().min(1),
|
|
448
|
+
expires_at: zDate,
|
|
449
|
+
})
|
|
450
|
+
.passthrough();
|
|
451
|
+
|
|
452
|
+
/** Espelha `ITeleconsultationAccessGrant`. `secret_hash` é HMAC — nunca o segredo. */
|
|
453
|
+
export const zTeleconsultationAccessGrantSchema = zFireDocSchema
|
|
454
|
+
.extend({
|
|
455
|
+
teleconsultation_id: z.string().min(1),
|
|
456
|
+
role: zParticipantRoleSchema,
|
|
457
|
+
kind: zAccessGrantKindSchema,
|
|
458
|
+
secret_hash: z.string().min(1),
|
|
459
|
+
recipient_ref_hash: z.string().optional(),
|
|
460
|
+
actor_user_id: z.string().optional(),
|
|
461
|
+
participant_id: z.string().optional(),
|
|
462
|
+
state: zAccessGrantStateSchema,
|
|
463
|
+
expires_at: zDate,
|
|
464
|
+
consumed_at: zDateNullable,
|
|
465
|
+
revoked_at: zDateNullable,
|
|
466
|
+
revoked_by: z.string().optional(),
|
|
467
|
+
last_used_at: zDateNullable,
|
|
468
|
+
failed_attempts: z.number().int().min(0),
|
|
469
|
+
failed_window_started_at: zDateNullable,
|
|
470
|
+
blocked_until: zDateNullable,
|
|
471
|
+
parent_grant_id: z.string().optional(),
|
|
472
|
+
channel_kind: zAccessSendChannelKindSchema.optional(),
|
|
473
|
+
quick_reply_action_id: z.string().optional(),
|
|
474
|
+
version: z.number().int().min(0),
|
|
475
|
+
})
|
|
476
|
+
.passthrough();
|
|
477
|
+
|
|
478
|
+
/** Espelha `ITelemedicineAppointmentIndex`. */
|
|
479
|
+
export const zTelemedicineAppointmentIndexSchema = zFireDocSchema
|
|
480
|
+
.extend({
|
|
481
|
+
calendar_id: z.string().min(1),
|
|
482
|
+
appointment_id: z.string().min(1),
|
|
483
|
+
active_teleconsultation_id: z.string().nullable(),
|
|
484
|
+
generation: z.number().int().min(0),
|
|
485
|
+
last_reconciled_appointment_version: z
|
|
486
|
+
.union([z.number(), z.string()])
|
|
487
|
+
.nullable()
|
|
488
|
+
.optional(),
|
|
489
|
+
})
|
|
490
|
+
.passthrough();
|
|
491
|
+
|
|
492
|
+
/** Espelha `ITelemedicineEntitlementAudit`. */
|
|
493
|
+
export const zTelemedicineEntitlementAuditSchema = zFireDocSchema
|
|
494
|
+
.extend({
|
|
495
|
+
module: z.string().min(1).max(40),
|
|
496
|
+
action: zEntitlementAuditActionSchema,
|
|
497
|
+
before: zTenantModuleEntitlementSchema.nullable().optional(),
|
|
498
|
+
after: zTenantModuleEntitlementSchema,
|
|
499
|
+
actor: z
|
|
500
|
+
.object({
|
|
501
|
+
type: z.enum(["user", "system", "script"]),
|
|
502
|
+
id: z.string().optional(),
|
|
503
|
+
})
|
|
504
|
+
.passthrough(),
|
|
505
|
+
reason: z.string().min(1).max(500),
|
|
506
|
+
occurred_at: zDate,
|
|
507
|
+
correlation_id: z.string().optional(),
|
|
508
|
+
})
|
|
509
|
+
.passthrough();
|
|
510
|
+
|
|
511
|
+
// ----- Documentos de plataforma -------------------------------------------------
|
|
512
|
+
|
|
513
|
+
// Docs globais (`IFireGlobalDoc`): sem `tenant`.
|
|
514
|
+
const zGlobalDocSchema = z.object({
|
|
515
|
+
id: z.string(),
|
|
516
|
+
ref: z.any().optional(),
|
|
517
|
+
model_ver: z.number().optional(),
|
|
518
|
+
version: z.number().optional(),
|
|
519
|
+
created_at: zDateNullable,
|
|
520
|
+
updated_at: zDateNullable,
|
|
521
|
+
deleted_at: zDateNullable,
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
/** Espelha `ITelemedicineLegalText` (standalone: `version` aqui é a versão do texto). */
|
|
525
|
+
export const zTelemedicineLegalTextSchema = z
|
|
526
|
+
.object({
|
|
527
|
+
id: z.string(),
|
|
528
|
+
subject: zConsentSubjectSchema,
|
|
529
|
+
locale: z.string().min(2).max(10),
|
|
530
|
+
version: z.string().min(1).max(40),
|
|
531
|
+
title: z.string().min(1).max(200),
|
|
532
|
+
content_html: z.string().min(1),
|
|
533
|
+
content_hash: z.string().min(1),
|
|
534
|
+
published_at: zDateNullable,
|
|
535
|
+
effective_at: zDateNullable,
|
|
536
|
+
status: zLegalTextStatusSchema,
|
|
537
|
+
placeholders: z.array(z.string().min(1).max(60)).optional(),
|
|
538
|
+
created_at: zDateNullable,
|
|
539
|
+
updated_at: zDateNullable,
|
|
540
|
+
})
|
|
541
|
+
.passthrough();
|
|
542
|
+
|
|
543
|
+
/** Espelha `ITelemedicineRollout`. Ausência do doc = deny. */
|
|
544
|
+
export const zTelemedicineRolloutSchema = zGlobalDocSchema
|
|
545
|
+
.extend({
|
|
546
|
+
create_enabled: z.boolean(),
|
|
547
|
+
join_enabled: z.boolean(),
|
|
548
|
+
recording_enabled: z.boolean(),
|
|
549
|
+
transcription_enabled: z.boolean(),
|
|
550
|
+
emergency_kill: z.boolean(),
|
|
551
|
+
updated_at: zDate,
|
|
552
|
+
updated_by: z.string().min(1),
|
|
553
|
+
})
|
|
554
|
+
.passthrough();
|
|
555
|
+
|
|
556
|
+
/** Espelha `ITelemedicineTranscriptionConfig`. */
|
|
557
|
+
export const zTelemedicineTranscriptionConfigSchema = zGlobalDocSchema
|
|
558
|
+
.extend({
|
|
559
|
+
provider: zTranscriptionProviderSchema,
|
|
560
|
+
production_gate_approved: z.boolean(),
|
|
561
|
+
approved_by: z.string().optional(),
|
|
562
|
+
approved_at: zDateNullable,
|
|
563
|
+
})
|
|
564
|
+
.passthrough();
|
|
565
|
+
|
|
566
|
+
/** Espelha `ITelemedicineGrantIndex`. */
|
|
567
|
+
export const zTelemedicineGrantIndexSchema = zGlobalDocSchema
|
|
568
|
+
.extend({
|
|
569
|
+
tenant: z.string().min(1),
|
|
570
|
+
teleconsultation_id: z.string().min(1),
|
|
571
|
+
grant_id: z.string().min(1),
|
|
572
|
+
expires_at: zDate,
|
|
573
|
+
})
|
|
574
|
+
.passthrough();
|
|
575
|
+
|
|
576
|
+
// ----- Comandos (request bodies — fronteira HTTP, estritos) --------------------
|
|
577
|
+
|
|
578
|
+
const zExpectedVersion = z.number().int().min(0).optional();
|
|
579
|
+
const zReason = z.string().trim().min(1).max(500);
|
|
580
|
+
|
|
581
|
+
/** `PATCH /waiting-policy` — espelha `IWaitingPolicyCommand`. */
|
|
582
|
+
export const zWaitingPolicyCommandSchema = z
|
|
583
|
+
.object({
|
|
584
|
+
waiting_policy: zWaitingPolicySchema,
|
|
585
|
+
expected_version: zExpectedVersion,
|
|
586
|
+
})
|
|
587
|
+
.strict();
|
|
588
|
+
|
|
589
|
+
/** `POST /reassign-host` — espelha `IReassignHostCommand` (motivo obrigatório, D22). */
|
|
590
|
+
export const zReassignHostCommandSchema = z
|
|
591
|
+
.object({
|
|
592
|
+
to_user_id: z.string().trim().min(1).max(128),
|
|
593
|
+
reason: zReason,
|
|
594
|
+
expected_version: zExpectedVersion,
|
|
595
|
+
})
|
|
596
|
+
.strict();
|
|
597
|
+
|
|
598
|
+
/** `POST /access/send` — espelha `IAccessSendCommand`. */
|
|
599
|
+
export const zAccessSendCommandSchema = z
|
|
600
|
+
.object({
|
|
601
|
+
channel_kind: zAccessSendChannelKindSchema,
|
|
602
|
+
resend: z.boolean().optional(),
|
|
603
|
+
})
|
|
604
|
+
.strict();
|
|
605
|
+
|
|
606
|
+
/** `POST /access/revoke` — espelha `IAccessRevokeCommand`. */
|
|
607
|
+
export const zAccessRevokeCommandSchema = z
|
|
608
|
+
.object({
|
|
609
|
+
grant_id: z.string().trim().min(1).max(128).optional(),
|
|
610
|
+
reason: zReason,
|
|
611
|
+
})
|
|
612
|
+
.strict();
|
|
613
|
+
|
|
614
|
+
/** `POST /end` — espelha `IEndCommand`. */
|
|
615
|
+
export const zEndCommandSchema = z
|
|
616
|
+
.object({
|
|
617
|
+
reason: z.string().trim().min(1).max(120).optional(),
|
|
618
|
+
expected_version: zExpectedVersion,
|
|
619
|
+
})
|
|
620
|
+
.strict();
|
|
621
|
+
|
|
622
|
+
/** `POST /api/room/v1/exchange` — espelha `IExchangeCommand` (code base64url de 128 bits = 22 chars). */
|
|
623
|
+
export const zExchangeCommandSchema = z
|
|
624
|
+
.object({
|
|
625
|
+
code: z
|
|
626
|
+
.string()
|
|
627
|
+
.trim()
|
|
628
|
+
.min(16)
|
|
629
|
+
.max(128)
|
|
630
|
+
.regex(/^[A-Za-z0-9_-]+$/, "code must be base64url"),
|
|
631
|
+
})
|
|
632
|
+
.strict();
|
|
633
|
+
|
|
634
|
+
/** `POST /api/room/v1/identity/verify` — espelha `IIdentityVerifyCommand`. */
|
|
635
|
+
export const zIdentityVerifyCommandSchema = z
|
|
636
|
+
.object({
|
|
637
|
+
display_name: z.string().trim().min(2).max(120),
|
|
638
|
+
// Normalizada no cliente para YYYY-MM-DD; o backend normaliza de novo antes
|
|
639
|
+
// da comparação constant-time. Erro de formato NÃO revela qual campo falhou.
|
|
640
|
+
birth_date: z
|
|
641
|
+
.string()
|
|
642
|
+
.trim()
|
|
643
|
+
.regex(/^\d{4}-\d{2}-\d{2}$/, "birth_date must be YYYY-MM-DD")
|
|
644
|
+
.optional(),
|
|
645
|
+
})
|
|
646
|
+
.strict();
|
|
647
|
+
|
|
648
|
+
/** `POST /api/room/v1/consents` — espelha `IConsentCommand` (só `accepted|declined`; retirada é rota de gravação). */
|
|
649
|
+
export const zConsentCommandSchema = z
|
|
650
|
+
.object({
|
|
651
|
+
subject: zConsentSubjectSchema,
|
|
652
|
+
terms_version: z.string().trim().min(1).max(40),
|
|
653
|
+
decision: z.enum(["accepted", "declined"]),
|
|
654
|
+
})
|
|
655
|
+
.strict();
|
|
656
|
+
|
|
657
|
+
/** `POST /api/room/v1/presence` — espelha `IPresenceCommand`. */
|
|
658
|
+
export const zPresenceCommandSchema = z
|
|
659
|
+
.object({
|
|
660
|
+
state: zPresenceStateSchema,
|
|
661
|
+
provider_participant_id: z.string().trim().min(1).max(128).optional(),
|
|
662
|
+
})
|
|
663
|
+
.strict();
|
|
664
|
+
|
|
665
|
+
/** `POST /api/room/v1/admit` — espelha `IAdmitCommand`. */
|
|
666
|
+
export const zAdmitCommandSchema = z
|
|
667
|
+
.object({
|
|
668
|
+
participant_id: z.string().trim().min(1).max(128),
|
|
669
|
+
})
|
|
670
|
+
.strict();
|
|
671
|
+
|
|
672
|
+
/** `POST /api/room/v1/reject` — espelha `IRejectCommand`. */
|
|
673
|
+
export const zRejectCommandSchema = z
|
|
674
|
+
.object({
|
|
675
|
+
participant_id: z.string().trim().min(1).max(128),
|
|
676
|
+
reason: z.string().trim().min(1).max(120).optional(),
|
|
677
|
+
})
|
|
678
|
+
.strict();
|
|
679
|
+
|
|
680
|
+
/** `POST /api/room/v1/recording/request` — espelha `IRecordingRequestCommand`. */
|
|
681
|
+
export const zRecordingRequestCommandSchema = z
|
|
682
|
+
.object({
|
|
683
|
+
recording_request_id: z.string().trim().min(8).max(128),
|
|
684
|
+
})
|
|
685
|
+
.strict();
|
|
686
|
+
|
|
687
|
+
/** `POST /api/room/v1/recording/accept|decline|withdraw` — espelha `IRecordingConsentCommand`. */
|
|
688
|
+
export const zRecordingConsentCommandSchema = z
|
|
689
|
+
.object({
|
|
690
|
+
recording_request_id: z.string().trim().min(8).max(128),
|
|
691
|
+
terms_version: z.string().trim().min(1).max(40),
|
|
692
|
+
})
|
|
693
|
+
.strict();
|
|
694
|
+
|
|
695
|
+
/** `POST /api/room/v1/recording/stop` — espelha `IRecordingStopCommand`. */
|
|
696
|
+
export const zRecordingStopCommandSchema = z
|
|
697
|
+
.object({
|
|
698
|
+
recording_request_id: z.string().trim().min(8).max(128).optional(),
|
|
699
|
+
})
|
|
700
|
+
.strict();
|
|
701
|
+
|
|
702
|
+
/** `POST /api/room/v1/telemetry` — espelha `ITelemetryCommand`; nomes allowlisted no backend. */
|
|
703
|
+
export const zTelemetryCommandSchema = z
|
|
704
|
+
.object({
|
|
705
|
+
events: z
|
|
706
|
+
.array(
|
|
707
|
+
z
|
|
708
|
+
.object({
|
|
709
|
+
name: z.string().trim().min(1).max(60),
|
|
710
|
+
at: z.string().datetime({ offset: true }),
|
|
711
|
+
attrs: z
|
|
712
|
+
.record(
|
|
713
|
+
z.string().min(1).max(40),
|
|
714
|
+
z.union([z.string().max(200), z.number(), z.boolean()])
|
|
715
|
+
)
|
|
716
|
+
.optional(),
|
|
717
|
+
})
|
|
718
|
+
.strict()
|
|
719
|
+
)
|
|
720
|
+
.min(1)
|
|
721
|
+
.max(50),
|
|
722
|
+
})
|
|
723
|
+
.strict();
|