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.
Files changed (44) hide show
  1. package/dist/apps/evo-crm/lead/zod-schemas.d.ts +9 -9
  2. package/dist/apps/evo-csq/zod-schemas.d.ts +12 -12
  3. package/dist/apps/evo-finops/zod-schemas.d.ts +18 -18
  4. package/dist/apps/evo-med/dic/zod-schemas.d.ts +2 -2
  5. package/dist/apps/evo-med/people/zod-schemas.d.ts +45 -45
  6. package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.d.ts +3 -0
  7. package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.js +3 -0
  8. package/dist/apps/evo-notifications/quick-reply-action/zod-schemas.ts +3 -0
  9. package/dist/apps/evo-notifications/zod-schemas.d.ts +69 -39
  10. package/dist/apps/evo-task/zod-schemas.d.ts +69 -69
  11. package/dist/apps/evo-task/zod-schemas.js +8 -0
  12. package/dist/apps/evo-task/zod-schemas.ts +8 -0
  13. package/dist/apps/evo-telemedicine/zod-schemas.d.ts +1445 -0
  14. package/dist/apps/evo-telemedicine/zod-schemas.js +641 -0
  15. package/dist/apps/evo-telemedicine/zod-schemas.ts +723 -0
  16. package/dist/apps/evo-tenant/zod-schemas.d.ts +94 -0
  17. package/dist/apps/evo-tenant/zod-schemas.js +29 -1
  18. package/dist/apps/evo-tenant/zod-schemas.ts +32 -1
  19. package/dist/apps/hub-automation/zod-schemas.d.ts +172 -172
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.js +2 -0
  22. package/dist/index.ts +2 -0
  23. package/dist/types/evo-med/calendar/index.d.ts +6 -0
  24. package/dist/types/evo-med/calendar/index.js +6 -0
  25. package/dist/types/evo-med/calendar/index.ts +6 -0
  26. package/dist/types/evo-notifications/index.d.ts +13 -0
  27. package/dist/types/evo-notifications/index.js +6 -0
  28. package/dist/types/evo-notifications/index.ts +13 -0
  29. package/dist/types/evo-task/index.d.ts +1 -0
  30. package/dist/types/evo-task/index.js +8 -0
  31. package/dist/types/evo-task/index.ts +8 -0
  32. package/dist/types/evo-telemedicine/fb_collections.d.ts +16 -0
  33. package/dist/types/evo-telemedicine/fb_collections.js +38 -0
  34. package/dist/types/evo-telemedicine/fb_collections.ts +37 -0
  35. package/dist/types/evo-telemedicine/index.d.ts +890 -0
  36. package/dist/types/evo-telemedicine/index.js +361 -0
  37. package/dist/types/evo-telemedicine/index.ts +1046 -0
  38. package/dist/types/evo-tenant/index.d.ts +45 -0
  39. package/dist/types/evo-tenant/index.js +20 -1
  40. package/dist/types/evo-tenant/index.ts +65 -0
  41. package/dist/types/shared/external-links.d.ts +6 -0
  42. package/dist/types/shared/external-links.js +6 -0
  43. package/dist/types/shared/external-links.ts +6 -0
  44. 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();