evo360-types 1.3.614 → 1.3.618

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.
@@ -27,6 +27,14 @@ export interface IDomainEventResource {
27
27
  parent?: {
28
28
  calendar_id?: string;
29
29
  } | null;
30
+ /**
31
+ * feat-205: discriminador de OCORRÊNCIA sobre o MESMO recurso (ex.: a NF
32
+ * emitida para a consulta — `occurrence_id` = invoiceId). Quando presente,
33
+ * entra na identidade da rotina (idempotency key da task materializada), de
34
+ * modo que duas ocorrências distintas sobre o mesmo recurso no mesmo dia não
35
+ * colapsam. Ausente = identidade legada, byte a byte igual.
36
+ */
37
+ occurrence_id?: string | null;
30
38
  }
31
39
  /**
32
40
  * Envelope canonico de um evento de dominio. Publicado em DOMAIN_EVENTS_TOPIC.
@@ -46,6 +46,14 @@ export interface IDomainEventResource {
46
46
  path?: string | null;
47
47
  /** hierarquia (ex.: calendar_id do appointment) para reconstruir o alvo. */
48
48
  parent?: { calendar_id?: string } | null;
49
+ /**
50
+ * feat-205: discriminador de OCORRÊNCIA sobre o MESMO recurso (ex.: a NF
51
+ * emitida para a consulta — `occurrence_id` = invoiceId). Quando presente,
52
+ * entra na identidade da rotina (idempotency key da task materializada), de
53
+ * modo que duas ocorrências distintas sobre o mesmo recurso no mesmo dia não
54
+ * colapsam. Ausente = identidade legada, byte a byte igual.
55
+ */
56
+ occurrence_id?: string | null;
49
57
  }
50
58
 
51
59
  // ── Envelope ──
@@ -62,6 +62,7 @@ export declare const TaskAutoHandlerEnum: {
62
62
  readonly CampaignMaterialize: "campaign.materialize";
63
63
  readonly CampaignDispatchBatch: "campaign.dispatch_batch";
64
64
  readonly TelemedicineJoinReminder: "telemedicine_join_reminder";
65
+ readonly AppointmentInvoice: "appointment_invoice";
65
66
  };
66
67
  export type TaskAutoHandler = (typeof TaskAutoHandlerEnum)[keyof typeof TaskAutoHandlerEnum];
67
68
  export declare const TaskRetryStrategyEnum: {
@@ -137,6 +137,14 @@ exports.TaskAutoHandlerEnum = {
137
137
  // `telemedicine_join_reminder.execute_requests`.
138
138
  // Espelhado à mão em `zTaskAutoHandlerSchema` — sem lá, criar a task estoura ZodError.
139
139
  TelemedicineJoinReminder: "telemedicine_join_reminder",
140
+ // feat-205: envio da NFS-e autorizada ao paciente — variant do executor único
141
+ // do lembrete (functions-integrations), lendo
142
+ // `notification_config.configs.appointment_invoice`; disparado pelo evento
143
+ // `agendamento.nf_emitida`. Entrega um link `/qr` (`invoice_link`) para o PDF
144
+ // no WhatsApp (botão URL) e no e-mail (`linknf`). Tópico:
145
+ // `appointment_invoice.execute_requests`.
146
+ // Espelhado à mão em `zTaskAutoHandlerSchema` — sem lá, criar a task estoura ZodError.
147
+ AppointmentInvoice: "appointment_invoice",
140
148
  };
141
149
  // ----- Retry policy
142
150
  exports.TaskRetryStrategyEnum = {
@@ -148,6 +148,14 @@ export const TaskAutoHandlerEnum = {
148
148
  // `telemedicine_join_reminder.execute_requests`.
149
149
  // Espelhado à mão em `zTaskAutoHandlerSchema` — sem lá, criar a task estoura ZodError.
150
150
  TelemedicineJoinReminder: "telemedicine_join_reminder",
151
+ // feat-205: envio da NFS-e autorizada ao paciente — variant do executor único
152
+ // do lembrete (functions-integrations), lendo
153
+ // `notification_config.configs.appointment_invoice`; disparado pelo evento
154
+ // `agendamento.nf_emitida`. Entrega um link `/qr` (`invoice_link`) para o PDF
155
+ // no WhatsApp (botão URL) e no e-mail (`linknf`). Tópico:
156
+ // `appointment_invoice.execute_requests`.
157
+ // Espelhado à mão em `zTaskAutoHandlerSchema` — sem lá, criar a task estoura ZodError.
158
+ AppointmentInvoice: "appointment_invoice",
151
159
  } as const;
152
160
 
153
161
  export type TaskAutoHandler =
@@ -82,9 +82,20 @@ export declare const TeleconsultationProviderEnum: {
82
82
  readonly RealtimeKit: "realtimekit";
83
83
  };
84
84
  export type TeleconsultationProvider = (typeof TeleconsultationProviderEnum)[keyof typeof TeleconsultationProviderEnum];
85
+ /**
86
+ * Papel do participante LÓGICO dentro da sala.
87
+ *
88
+ * `guest` (feat-160 R8, 2026-09-25) é o acompanhante: até 3 por sala, cada um
89
+ * num slot próprio (`guest-1..3`), entrando pelo MESMO link do paciente. Ele
90
+ * não é papel de GRANT — o grant continua `patient`, porque o link é o do
91
+ * titular; o que decide `guest` é a alocação de slot no momento da entrada
92
+ * (`allocateParticipantSlot`). Um acompanhante nunca tem `patient_id` e nunca
93
+ * herda o consentimento do paciente.
94
+ */
85
95
  export declare const ParticipantRoleEnum: {
86
96
  readonly Doctor: "doctor";
87
97
  readonly Patient: "patient";
98
+ readonly Guest: "guest";
88
99
  };
89
100
  export type ParticipantRole = (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum];
90
101
  /** Presença — separada do estado clínico da teleconsulta. */
@@ -257,6 +268,16 @@ export declare const TeleconsultationEventTypeEnum: {
257
268
  readonly PatientDisconnected: "patient.disconnected";
258
269
  readonly PatientRejoined: "patient.rejoined";
259
270
  readonly PatientLeft: "patient.left";
271
+ /**
272
+ * feat-160 R8 — peer EXCEDENTE de um participante que já estava `connected`
273
+ * (duas abas com o mesmo token). É a segunda perna da trava de ocupação: a
274
+ * primeira recusa a quinta pessoa na EMISSÃO, esta derruba quem duplicou a
275
+ * OCUPAÇÃO — sem ela a Cloudflare cobraria as duas abas.
276
+ *
277
+ * Não é `patient.disconnected` (aquela é presença de quem estava dentro) nem
278
+ * `access.blocked` (aquela é lockout de identidade no grant).
279
+ */
280
+ readonly ParticipantDuplicatePeer: "participant.duplicate_peer";
260
281
  readonly RecordingConsentRequested: "recording.consent_requested";
261
282
  readonly RecordingConsentAccepted: "recording.consent_accepted";
262
283
  readonly RecordingConsentDeclined: "recording.consent_declined";
@@ -487,6 +508,26 @@ export interface ITeleconsultationParticipant extends IFireDoc {
487
508
  /** `custom_participant_id` opaco enviado ao provider — nunca o patientId. */
488
509
  opaque_custom_participant_id: string;
489
510
  state: ParticipantState;
511
+ /**
512
+ * feat-160 R8 — ordinal do acompanhante (1..3). Só para `role = guest`; é o
513
+ * número da etiqueta ("Acompanhante 2") e o que ordena os blocos na tela.
514
+ * Ausente para médico e paciente, que têm slot único.
515
+ */
516
+ slot_ordinal?: number;
517
+ /**
518
+ * feat-160 R8 — id estável do NAVEGADOR que ocupa este slot.
519
+ *
520
+ * A sessão pública rotaciona (`browser_session` nova a cada refresh, com
521
+ * `parent_grant_id = root_grant_id`), então nem o grant da sessão nem o
522
+ * grant raiz servem de "quem é este navegador": o primeiro muda a cada
523
+ * rotação e o segundo é o MESMO para todos que usam o link do paciente. Este
524
+ * campo é esse elo: gerado no `/exchange`, copiado na rotação, e gravado
525
+ * aqui quando o slot é alocado — é o que faz recarregar a página manter a
526
+ * etiqueta em vez de reembaralhar.
527
+ *
528
+ * Opaco (128 bits em base64url), não é segredo e não identifica pessoa.
529
+ */
530
+ session_family_id?: string;
490
531
  identity_level?: IdentityLevel;
491
532
  admitted_at?: Date | null;
492
533
  connected_at?: Date | null;
@@ -610,6 +651,16 @@ export interface ITeleconsultationAccessGrant extends IFireDoc {
610
651
  blocked_until?: Date | null;
611
652
  /** `launch_code` filho de `qr_capability`; `browser_session` filho do code/capability. */
612
653
  parent_grant_id?: string;
654
+ /**
655
+ * feat-160 R8 — família de sessões de UM navegador.
656
+ *
657
+ * Nasce no `/exchange` e é COPIADA em cada rotação, então a cadeia de
658
+ * `browser_session` de um mesmo navegador compartilha este id enquanto
659
+ * `parent_grant_id` (o grant raiz) é compartilhado por TODOS os navegadores
660
+ * que usaram o link. É por ele que o slot alocado (`participant_id`) volta
661
+ * para o mesmo dono depois de um reload.
662
+ */
663
+ session_family_id?: string;
613
664
  /** Canal do envio que originou o grant (`qr_capability`). */
614
665
  channel_kind?: AccessSendChannelKind;
615
666
  /** Doc `quick-reply-actions/{actionId}` ligado ao grant — cancelado no revoke. */
@@ -772,6 +823,13 @@ export declare const TelemedicineErrorCode: {
772
823
  readonly ProviderError: "PROVIDER_ERROR";
773
824
  /** 429 — rate limit por IP-hash/grant. */
774
825
  readonly RateLimited: "RATE_LIMITED";
826
+ /**
827
+ * 409 — sala cheia (feat-160 R8): médico + paciente + 3 acompanhantes, e
828
+ * nenhum slot livre no instante da entrada. O teto é NOSSO — o provedor não
829
+ * oferece limite de participantes (página de limites conferida em
830
+ * 2026-09-25) —, e ele é de EMISSÃO: quem recebe este erro não recebe token.
831
+ */
832
+ readonly RoomFull: "ROOM_FULL";
775
833
  /** 400 — body/params inválidos. */
776
834
  readonly ValidationError: "VALIDATION_ERROR";
777
835
  };
@@ -786,6 +844,12 @@ export interface ITeleconsultationParticipantDto {
786
844
  participant_id: string;
787
845
  role: ParticipantRole;
788
846
  state: ParticipantState;
847
+ /**
848
+ * feat-160 R8 — ordinal do acompanhante (1..3), quando `role = guest`. É o
849
+ * número da etiqueta na tela; `session_family_id` NÃO sai no DTO (é estado
850
+ * interno de alocação, não interessa ao cliente).
851
+ */
852
+ slot_ordinal?: number;
789
853
  identity_level?: IdentityLevel;
790
854
  admitted_at?: string | null;
791
855
  connected_at?: string | null;
@@ -1060,7 +1124,7 @@ export interface ISignedUrlResponseDto {
1060
1124
  /** Modo efetivamente aplicado (`attachment` quando o comando omite). */
1061
1125
  disposition?: ArtifactDisposition;
1062
1126
  }
1063
- export type TranscriptSpeakerRole = "doctor" | "patient" | "unknown";
1127
+ export type TranscriptSpeakerRole = "doctor" | "patient" | "guest" | "unknown";
1064
1128
  export interface ITranscriptSpeakerDto {
1065
1129
  /** `opaque_custom_participant_id` que amarra a fala ao papel. */
1066
1130
  key: string;
@@ -116,9 +116,20 @@ exports.TeleconsultationModeEnum = {
116
116
  exports.TeleconsultationProviderEnum = {
117
117
  RealtimeKit: "realtimekit",
118
118
  };
119
+ /**
120
+ * Papel do participante LÓGICO dentro da sala.
121
+ *
122
+ * `guest` (feat-160 R8, 2026-09-25) é o acompanhante: até 3 por sala, cada um
123
+ * num slot próprio (`guest-1..3`), entrando pelo MESMO link do paciente. Ele
124
+ * não é papel de GRANT — o grant continua `patient`, porque o link é o do
125
+ * titular; o que decide `guest` é a alocação de slot no momento da entrada
126
+ * (`allocateParticipantSlot`). Um acompanhante nunca tem `patient_id` e nunca
127
+ * herda o consentimento do paciente.
128
+ */
119
129
  exports.ParticipantRoleEnum = {
120
130
  Doctor: "doctor",
121
131
  Patient: "patient",
132
+ Guest: "guest",
122
133
  };
123
134
  /** Presença — separada do estado clínico da teleconsulta. */
124
135
  exports.ParticipantStateEnum = {
@@ -274,6 +285,16 @@ exports.TeleconsultationEventTypeEnum = {
274
285
  PatientDisconnected: "patient.disconnected",
275
286
  PatientRejoined: "patient.rejoined",
276
287
  PatientLeft: "patient.left",
288
+ /**
289
+ * feat-160 R8 — peer EXCEDENTE de um participante que já estava `connected`
290
+ * (duas abas com o mesmo token). É a segunda perna da trava de ocupação: a
291
+ * primeira recusa a quinta pessoa na EMISSÃO, esta derruba quem duplicou a
292
+ * OCUPAÇÃO — sem ela a Cloudflare cobraria as duas abas.
293
+ *
294
+ * Não é `patient.disconnected` (aquela é presença de quem estava dentro) nem
295
+ * `access.blocked` (aquela é lockout de identidade no grant).
296
+ */
297
+ ParticipantDuplicatePeer: "participant.duplicate_peer",
277
298
  RecordingConsentRequested: "recording.consent_requested",
278
299
  RecordingConsentAccepted: "recording.consent_accepted",
279
300
  RecordingConsentDeclined: "recording.consent_declined",
@@ -411,6 +432,13 @@ exports.TelemedicineErrorCode = {
411
432
  ProviderError: "PROVIDER_ERROR",
412
433
  /** 429 — rate limit por IP-hash/grant. */
413
434
  RateLimited: "RATE_LIMITED",
435
+ /**
436
+ * 409 — sala cheia (feat-160 R8): médico + paciente + 3 acompanhantes, e
437
+ * nenhum slot livre no instante da entrada. O teto é NOSSO — o provedor não
438
+ * oferece limite de participantes (página de limites conferida em
439
+ * 2026-09-25) —, e ele é de EMISSÃO: quem recebe este erro não recebe token.
440
+ */
441
+ RoomFull: "ROOM_FULL",
414
442
  /** 400 — body/params inválidos. */
415
443
  ValidationError: "VALIDATION_ERROR",
416
444
  };
@@ -126,9 +126,20 @@ export const TeleconsultationProviderEnum = {
126
126
  export type TeleconsultationProvider =
127
127
  (typeof TeleconsultationProviderEnum)[keyof typeof TeleconsultationProviderEnum];
128
128
 
129
+ /**
130
+ * Papel do participante LÓGICO dentro da sala.
131
+ *
132
+ * `guest` (feat-160 R8, 2026-09-25) é o acompanhante: até 3 por sala, cada um
133
+ * num slot próprio (`guest-1..3`), entrando pelo MESMO link do paciente. Ele
134
+ * não é papel de GRANT — o grant continua `patient`, porque o link é o do
135
+ * titular; o que decide `guest` é a alocação de slot no momento da entrada
136
+ * (`allocateParticipantSlot`). Um acompanhante nunca tem `patient_id` e nunca
137
+ * herda o consentimento do paciente.
138
+ */
129
139
  export const ParticipantRoleEnum = {
130
140
  Doctor: "doctor",
131
141
  Patient: "patient",
142
+ Guest: "guest",
132
143
  } as const;
133
144
  export type ParticipantRole = (typeof ParticipantRoleEnum)[keyof typeof ParticipantRoleEnum];
134
145
 
@@ -325,6 +336,16 @@ export const TeleconsultationEventTypeEnum = {
325
336
  PatientDisconnected: "patient.disconnected",
326
337
  PatientRejoined: "patient.rejoined",
327
338
  PatientLeft: "patient.left",
339
+ /**
340
+ * feat-160 R8 — peer EXCEDENTE de um participante que já estava `connected`
341
+ * (duas abas com o mesmo token). É a segunda perna da trava de ocupação: a
342
+ * primeira recusa a quinta pessoa na EMISSÃO, esta derruba quem duplicou a
343
+ * OCUPAÇÃO — sem ela a Cloudflare cobraria as duas abas.
344
+ *
345
+ * Não é `patient.disconnected` (aquela é presença de quem estava dentro) nem
346
+ * `access.blocked` (aquela é lockout de identidade no grant).
347
+ */
348
+ ParticipantDuplicatePeer: "participant.duplicate_peer",
328
349
  RecordingConsentRequested: "recording.consent_requested",
329
350
  RecordingConsentAccepted: "recording.consent_accepted",
330
351
  RecordingConsentDeclined: "recording.consent_declined",
@@ -578,6 +599,26 @@ export interface ITeleconsultationParticipant extends IFireDoc {
578
599
  /** `custom_participant_id` opaco enviado ao provider — nunca o patientId. */
579
600
  opaque_custom_participant_id: string;
580
601
  state: ParticipantState;
602
+ /**
603
+ * feat-160 R8 — ordinal do acompanhante (1..3). Só para `role = guest`; é o
604
+ * número da etiqueta ("Acompanhante 2") e o que ordena os blocos na tela.
605
+ * Ausente para médico e paciente, que têm slot único.
606
+ */
607
+ slot_ordinal?: number;
608
+ /**
609
+ * feat-160 R8 — id estável do NAVEGADOR que ocupa este slot.
610
+ *
611
+ * A sessão pública rotaciona (`browser_session` nova a cada refresh, com
612
+ * `parent_grant_id = root_grant_id`), então nem o grant da sessão nem o
613
+ * grant raiz servem de "quem é este navegador": o primeiro muda a cada
614
+ * rotação e o segundo é o MESMO para todos que usam o link do paciente. Este
615
+ * campo é esse elo: gerado no `/exchange`, copiado na rotação, e gravado
616
+ * aqui quando o slot é alocado — é o que faz recarregar a página manter a
617
+ * etiqueta em vez de reembaralhar.
618
+ *
619
+ * Opaco (128 bits em base64url), não é segredo e não identifica pessoa.
620
+ */
621
+ session_family_id?: string;
581
622
  identity_level?: IdentityLevel;
582
623
  admitted_at?: Date | null;
583
624
  connected_at?: Date | null;
@@ -707,6 +748,16 @@ export interface ITeleconsultationAccessGrant extends IFireDoc {
707
748
  blocked_until?: Date | null;
708
749
  /** `launch_code` filho de `qr_capability`; `browser_session` filho do code/capability. */
709
750
  parent_grant_id?: string;
751
+ /**
752
+ * feat-160 R8 — família de sessões de UM navegador.
753
+ *
754
+ * Nasce no `/exchange` e é COPIADA em cada rotação, então a cadeia de
755
+ * `browser_session` de um mesmo navegador compartilha este id enquanto
756
+ * `parent_grant_id` (o grant raiz) é compartilhado por TODOS os navegadores
757
+ * que usaram o link. É por ele que o slot alocado (`participant_id`) volta
758
+ * para o mesmo dono depois de um reload.
759
+ */
760
+ session_family_id?: string;
710
761
  /** Canal do envio que originou o grant (`qr_capability`). */
711
762
  channel_kind?: AccessSendChannelKind;
712
763
  /** Doc `quick-reply-actions/{actionId}` ligado ao grant — cancelado no revoke. */
@@ -891,6 +942,13 @@ export const TelemedicineErrorCode = {
891
942
  ProviderError: "PROVIDER_ERROR",
892
943
  /** 429 — rate limit por IP-hash/grant. */
893
944
  RateLimited: "RATE_LIMITED",
945
+ /**
946
+ * 409 — sala cheia (feat-160 R8): médico + paciente + 3 acompanhantes, e
947
+ * nenhum slot livre no instante da entrada. O teto é NOSSO — o provedor não
948
+ * oferece limite de participantes (página de limites conferida em
949
+ * 2026-09-25) —, e ele é de EMISSÃO: quem recebe este erro não recebe token.
950
+ */
951
+ RoomFull: "ROOM_FULL",
894
952
  /** 400 — body/params inválidos. */
895
953
  ValidationError: "VALIDATION_ERROR",
896
954
  } as const;
@@ -913,6 +971,12 @@ export interface ITeleconsultationParticipantDto {
913
971
  participant_id: string;
914
972
  role: ParticipantRole;
915
973
  state: ParticipantState;
974
+ /**
975
+ * feat-160 R8 — ordinal do acompanhante (1..3), quando `role = guest`. É o
976
+ * número da etiqueta na tela; `session_family_id` NÃO sai no DTO (é estado
977
+ * interno de alocação, não interessa ao cliente).
978
+ */
979
+ slot_ordinal?: number;
916
980
  identity_level?: IdentityLevel;
917
981
  admitted_at?: string | null;
918
982
  connected_at?: string | null;
@@ -1208,7 +1272,7 @@ export interface ISignedUrlResponseDto {
1208
1272
  // `seekTo` e o `mm:ss` da bolha vem de arredondamento — dois consumidores do
1209
1273
  // mesmo número, e um `0.1 + 0.2` no meio é ruído garantido.
1210
1274
 
1211
- export type TranscriptSpeakerRole = "doctor" | "patient" | "unknown";
1275
+ export type TranscriptSpeakerRole = "doctor" | "patient" | "guest" | "unknown";
1212
1276
 
1213
1277
  export interface ITranscriptSpeakerDto {
1214
1278
  /** `opaque_custom_participant_id` que amarra a fala ao papel. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evo360-types",
3
- "version": "1.3.614",
3
+ "version": "1.3.618",
4
4
  "description": "HREVO360 Shared Types",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",