evo360-types 1.3.399 → 1.3.401
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/dic/zod-schemas.d.ts +6 -0
- package/dist/apps/evo-crm/dic/zod-schemas.js +12 -0
- package/dist/apps/evo-crm/dic/zod-schemas.ts +12 -0
- package/dist/apps/evo-finops/zod-schemas.d.ts +8 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.ts +1 -0
- package/dist/types/evo-crm/dic/index.d.ts +3 -0
- package/dist/types/evo-crm/dic/index.ts +13 -0
- package/dist/types/nexus-webhooks/index.d.ts +107 -0
- package/dist/types/nexus-webhooks/index.js +53 -0
- package/dist/types/nexus-webhooks/index.ts +187 -0
- package/package.json +1 -1
|
@@ -224,6 +224,8 @@ export declare const zQualificationSchema: z.ZodObject<{
|
|
|
224
224
|
color?: string | undefined;
|
|
225
225
|
category?: string | null | undefined;
|
|
226
226
|
}>, "many">>>;
|
|
227
|
+
meta_event: z.ZodOptional<z.ZodNullable<z.ZodEnum<["LeadSubmitted", "AppointmentBooked", "Purchase", "InitiateCheckout", "AddToCart", "ViewContent"]>>>;
|
|
228
|
+
meta_event_value: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
227
229
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
228
230
|
id: z.ZodString;
|
|
229
231
|
ref: z.ZodAny;
|
|
@@ -257,6 +259,8 @@ export declare const zQualificationSchema: z.ZodObject<{
|
|
|
257
259
|
color?: string | undefined;
|
|
258
260
|
category?: string | null | undefined;
|
|
259
261
|
}>, "many">>>;
|
|
262
|
+
meta_event: z.ZodOptional<z.ZodNullable<z.ZodEnum<["LeadSubmitted", "AppointmentBooked", "Purchase", "InitiateCheckout", "AddToCart", "ViewContent"]>>>;
|
|
263
|
+
meta_event_value: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
260
264
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
261
265
|
id: z.ZodString;
|
|
262
266
|
ref: z.ZodAny;
|
|
@@ -290,4 +294,6 @@ export declare const zQualificationSchema: z.ZodObject<{
|
|
|
290
294
|
color?: string | undefined;
|
|
291
295
|
category?: string | null | undefined;
|
|
292
296
|
}>, "many">>>;
|
|
297
|
+
meta_event: z.ZodOptional<z.ZodNullable<z.ZodEnum<["LeadSubmitted", "AppointmentBooked", "Purchase", "InitiateCheckout", "AddToCart", "ViewContent"]>>>;
|
|
298
|
+
meta_event_value: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
293
299
|
}, z.ZodTypeAny, "passthrough">>;
|
|
@@ -44,5 +44,17 @@ exports.zQualificationSchema = zod_schemas_1.zFireDocSchema
|
|
|
44
44
|
hide: zod_1.z.boolean().optional().default(false),
|
|
45
45
|
funnelHide: zod_1.z.boolean().optional().default(false),
|
|
46
46
|
tags: zod_1.z.array(zod_schemas_1.zTagSchema).nullable().optional(),
|
|
47
|
+
meta_event: zod_1.z
|
|
48
|
+
.enum([
|
|
49
|
+
"LeadSubmitted",
|
|
50
|
+
"AppointmentBooked",
|
|
51
|
+
"Purchase",
|
|
52
|
+
"InitiateCheckout",
|
|
53
|
+
"AddToCart",
|
|
54
|
+
"ViewContent",
|
|
55
|
+
])
|
|
56
|
+
.nullable()
|
|
57
|
+
.optional(),
|
|
58
|
+
meta_event_value: zod_1.z.number().positive().nullable().optional(),
|
|
47
59
|
})
|
|
48
60
|
.passthrough();
|
|
@@ -45,5 +45,17 @@ export const zQualificationSchema = zFireDocSchema
|
|
|
45
45
|
hide: z.boolean().optional().default(false),
|
|
46
46
|
funnelHide: z.boolean().optional().default(false),
|
|
47
47
|
tags: z.array(zTagSchema).nullable().optional(),
|
|
48
|
+
meta_event: z
|
|
49
|
+
.enum([
|
|
50
|
+
"LeadSubmitted",
|
|
51
|
+
"AppointmentBooked",
|
|
52
|
+
"Purchase",
|
|
53
|
+
"InitiateCheckout",
|
|
54
|
+
"AddToCart",
|
|
55
|
+
"ViewContent",
|
|
56
|
+
])
|
|
57
|
+
.nullable()
|
|
58
|
+
.optional(),
|
|
59
|
+
meta_event_value: z.number().positive().nullable().optional(),
|
|
48
60
|
})
|
|
49
61
|
.passthrough();
|
|
@@ -10682,18 +10682,18 @@ export declare const zProviderPayloadSnapshotSchema: z.ZodObject<{
|
|
|
10682
10682
|
raw?: string | undefined;
|
|
10683
10683
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
10684
10684
|
body?: unknown;
|
|
10685
|
+
headers?: Record<string, string> | undefined;
|
|
10685
10686
|
http_status?: number | undefined;
|
|
10686
10687
|
endpoint?: string | undefined;
|
|
10687
|
-
headers?: Record<string, string> | undefined;
|
|
10688
10688
|
}, {
|
|
10689
10689
|
direction: "webhook" | "request" | "response";
|
|
10690
10690
|
raw?: string | undefined;
|
|
10691
10691
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
10692
10692
|
at?: unknown;
|
|
10693
10693
|
body?: unknown;
|
|
10694
|
+
headers?: Record<string, string> | undefined;
|
|
10694
10695
|
http_status?: number | undefined;
|
|
10695
10696
|
endpoint?: string | undefined;
|
|
10696
|
-
headers?: Record<string, string> | undefined;
|
|
10697
10697
|
}>;
|
|
10698
10698
|
export declare const zAsaasPaymentLinkBillingTypeSchema: z.ZodEnum<["UNDEFINED", "BOLETO", "CREDIT_CARD", "PIX"]>;
|
|
10699
10699
|
export declare const zAsaasPaymentLinkChargeTypeSchema: z.ZodEnum<["DETACHED", "RECURRENT", "INSTALLMENT"]>;
|
|
@@ -11661,18 +11661,18 @@ export declare const zServiceInvoiceSchema: z.ZodObject<{
|
|
|
11661
11661
|
raw?: string | undefined;
|
|
11662
11662
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
11663
11663
|
body?: unknown;
|
|
11664
|
+
headers?: Record<string, string> | undefined;
|
|
11664
11665
|
http_status?: number | undefined;
|
|
11665
11666
|
endpoint?: string | undefined;
|
|
11666
|
-
headers?: Record<string, string> | undefined;
|
|
11667
11667
|
}, {
|
|
11668
11668
|
direction: "webhook" | "request" | "response";
|
|
11669
11669
|
raw?: string | undefined;
|
|
11670
11670
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
11671
11671
|
at?: unknown;
|
|
11672
11672
|
body?: unknown;
|
|
11673
|
+
headers?: Record<string, string> | undefined;
|
|
11673
11674
|
http_status?: number | undefined;
|
|
11674
11675
|
endpoint?: string | undefined;
|
|
11675
|
-
headers?: Record<string, string> | undefined;
|
|
11676
11676
|
}>, "many">>;
|
|
11677
11677
|
}, "passthrough", z.ZodTypeAny, z.objectOutputType<{
|
|
11678
11678
|
id: z.ZodString;
|
|
@@ -12080,18 +12080,18 @@ export declare const zServiceInvoiceSchema: z.ZodObject<{
|
|
|
12080
12080
|
raw?: string | undefined;
|
|
12081
12081
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
12082
12082
|
body?: unknown;
|
|
12083
|
+
headers?: Record<string, string> | undefined;
|
|
12083
12084
|
http_status?: number | undefined;
|
|
12084
12085
|
endpoint?: string | undefined;
|
|
12085
|
-
headers?: Record<string, string> | undefined;
|
|
12086
12086
|
}, {
|
|
12087
12087
|
direction: "webhook" | "request" | "response";
|
|
12088
12088
|
raw?: string | undefined;
|
|
12089
12089
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
12090
12090
|
at?: unknown;
|
|
12091
12091
|
body?: unknown;
|
|
12092
|
+
headers?: Record<string, string> | undefined;
|
|
12092
12093
|
http_status?: number | undefined;
|
|
12093
12094
|
endpoint?: string | undefined;
|
|
12094
|
-
headers?: Record<string, string> | undefined;
|
|
12095
12095
|
}>, "many">>;
|
|
12096
12096
|
}, z.ZodTypeAny, "passthrough">, z.objectInputType<{
|
|
12097
12097
|
id: z.ZodString;
|
|
@@ -12499,17 +12499,17 @@ export declare const zServiceInvoiceSchema: z.ZodObject<{
|
|
|
12499
12499
|
raw?: string | undefined;
|
|
12500
12500
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
12501
12501
|
body?: unknown;
|
|
12502
|
+
headers?: Record<string, string> | undefined;
|
|
12502
12503
|
http_status?: number | undefined;
|
|
12503
12504
|
endpoint?: string | undefined;
|
|
12504
|
-
headers?: Record<string, string> | undefined;
|
|
12505
12505
|
}, {
|
|
12506
12506
|
direction: "webhook" | "request" | "response";
|
|
12507
12507
|
raw?: string | undefined;
|
|
12508
12508
|
method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | undefined;
|
|
12509
12509
|
at?: unknown;
|
|
12510
12510
|
body?: unknown;
|
|
12511
|
+
headers?: Record<string, string> | undefined;
|
|
12511
12512
|
http_status?: number | undefined;
|
|
12512
12513
|
endpoint?: string | undefined;
|
|
12513
|
-
headers?: Record<string, string> | undefined;
|
|
12514
12514
|
}>, "many">>;
|
|
12515
12515
|
}, z.ZodTypeAny, "passthrough">>;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,7 @@ export * from "./types/evo-task-runner";
|
|
|
26
26
|
export * from "./types/evo-integrations";
|
|
27
27
|
export * from "./types/nex-customers";
|
|
28
28
|
export * from "./types/nex-tenants";
|
|
29
|
+
export * from "./types/nexus-webhooks";
|
|
29
30
|
export * from "./types/evo-hub-ia";
|
|
30
31
|
export * from "./types/evo-mcp";
|
|
31
32
|
export * from "./apps/shared/zod-schemas";
|
package/dist/index.js
CHANGED
|
@@ -43,6 +43,7 @@ __exportStar(require("./types/evo-task-runner"), exports);
|
|
|
43
43
|
__exportStar(require("./types/evo-integrations"), exports);
|
|
44
44
|
__exportStar(require("./types/nex-customers"), exports);
|
|
45
45
|
__exportStar(require("./types/nex-tenants"), exports);
|
|
46
|
+
__exportStar(require("./types/nexus-webhooks"), exports);
|
|
46
47
|
__exportStar(require("./types/evo-hub-ia"), exports);
|
|
47
48
|
__exportStar(require("./types/evo-mcp"), exports);
|
|
48
49
|
// zod schemas
|
package/dist/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ export * from "./types/evo-task-runner";
|
|
|
27
27
|
export * from "./types/evo-integrations";
|
|
28
28
|
export * from "./types/nex-customers";
|
|
29
29
|
export * from "./types/nex-tenants";
|
|
30
|
+
export * from "./types/nexus-webhooks";
|
|
30
31
|
export * from "./types/evo-hub-ia";
|
|
31
32
|
export * from "./types/evo-mcp";
|
|
32
33
|
|
|
@@ -62,11 +62,14 @@ export declare enum IQualificationFunnelLevel {
|
|
|
62
62
|
WaitingReply = "waiting_reply",// Aguardando retorno do lead
|
|
63
63
|
FollowUpLater = "follow_up_later"
|
|
64
64
|
}
|
|
65
|
+
export type MetaMessagingEventName = "LeadSubmitted" | "AppointmentBooked" | "Purchase" | "InitiateCheckout" | "AddToCart" | "ViewContent";
|
|
65
66
|
export interface IQualification extends IFireDoc {
|
|
66
67
|
code: string;
|
|
67
68
|
name: string;
|
|
68
69
|
funnelLevel: QualificationFunnelLevel;
|
|
69
70
|
hide?: boolean;
|
|
70
71
|
funnelHide?: boolean;
|
|
72
|
+
meta_event?: MetaMessagingEventName | null;
|
|
73
|
+
meta_event_value?: number | null;
|
|
71
74
|
[key: string]: unknown;
|
|
72
75
|
}
|
|
@@ -103,6 +103,16 @@ export enum IQualificationFunnelLevel {
|
|
|
103
103
|
FollowUpLater = "follow_up_later", // Contato agendado para o futuro
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
// Meta CAPI event names accepted for action_source=business_messaging.
|
|
107
|
+
// Confirmed empirically (feat-062 PASSO 0); pixel/web names (Lead, Schedule, Contact) are rejected by Meta.
|
|
108
|
+
export type MetaMessagingEventName =
|
|
109
|
+
| "LeadSubmitted"
|
|
110
|
+
| "AppointmentBooked"
|
|
111
|
+
| "Purchase"
|
|
112
|
+
| "InitiateCheckout"
|
|
113
|
+
| "AddToCart"
|
|
114
|
+
| "ViewContent";
|
|
115
|
+
|
|
106
116
|
// Lead qualification status
|
|
107
117
|
export interface IQualification extends IFireDoc {
|
|
108
118
|
code: string;
|
|
@@ -110,5 +120,8 @@ export interface IQualification extends IFireDoc {
|
|
|
110
120
|
funnelLevel: QualificationFunnelLevel;
|
|
111
121
|
hide?: boolean;
|
|
112
122
|
funnelHide?: boolean;
|
|
123
|
+
// feat-062: auto Meta CAPI conversion when a lead reaches this qualification.
|
|
124
|
+
meta_event?: MetaMessagingEventName | null;
|
|
125
|
+
meta_event_value?: number | null;
|
|
113
126
|
[key: string]: unknown; // index signature
|
|
114
127
|
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { IFireGlobalDoc } from "../shared";
|
|
2
|
+
/** Topico central: todo emitNexusEvent() publica aqui (envelope canonico). */
|
|
3
|
+
export declare const NEXUS_WEBHOOK_EVENTS_TOPIC: "nexus-webhook-events";
|
|
4
|
+
/** Topico de fan-out: 1 mensagem por (subscription x evento) casado. */
|
|
5
|
+
export declare const NEXUS_WEBHOOK_DELIVERIES_TOPIC: "nexus-webhook-deliveries";
|
|
6
|
+
/** Topico de auditoria: 1 mensagem por tentativa de entrega (sink BQ). */
|
|
7
|
+
export declare const NEXUS_WEBHOOK_DELIVERY_LOG_TOPIC: "nexus-webhook-delivery-log";
|
|
8
|
+
/** Raiz Firestore do registry (subdocs `private/secret` guardam o segredo). */
|
|
9
|
+
export declare const NEXUS_WEBHOOKS_PLATFORM_PATH: "platform/nexus-webhooks";
|
|
10
|
+
/** Versao do contrato do envelope, carimbada em `api_version`. */
|
|
11
|
+
export declare const NEXUS_WEBHOOK_API_VERSION: "2026-07-01";
|
|
12
|
+
export type NexusWebhookActorKind = "user" | "system" | "provider";
|
|
13
|
+
export type NexusWebhookDeliveryStatus = "pending" | "delivered" | "failed" | "dead_letter";
|
|
14
|
+
/** Catalogo v1 de tipos de evento. Alimenta `GET /event-types` e a validacao
|
|
15
|
+
* de filtros das subscriptions (globs sao validados a parte). */
|
|
16
|
+
export declare const NEXUS_WEBHOOK_EVENT_TYPES: readonly ["tenant.created", "tenant.updated", "tenant.status_changed", "finops.customer.created", "finops.customer.updated", "finops.customer.status_changed", "finops.customer.deleted", "finops.contract.created", "finops.contract.updated", "finops.contract.status_changed", "finops.contract.deleted", "finops.billing.created", "finops.billing.updated", "finops.billing.status_changed", "finops.billing.deleted", "finops.invoice.created", "finops.invoice.updated", "finops.invoice.status_changed", "finops.invoice.deleted", "finops.payment.received", "forms.onboarding.submitted", "forms.onboarding.updated", "forms.onboarding.completed"];
|
|
17
|
+
export type NexusWebhookEventType = (typeof NEXUS_WEBHOOK_EVENT_TYPES)[number];
|
|
18
|
+
export interface INexusWebhookActor {
|
|
19
|
+
kind: NexusWebhookActorKind;
|
|
20
|
+
/** uid do usuario, nome do sistema, ou nome do provider (asaas/inter/...). */
|
|
21
|
+
id: string | null;
|
|
22
|
+
}
|
|
23
|
+
export interface INexusWebhookResource {
|
|
24
|
+
/** ex.: 'customer', 'contract', 'billing', 'invoice', 'tenant', 'form'. */
|
|
25
|
+
kind: string;
|
|
26
|
+
id: string;
|
|
27
|
+
/** caminho Firestore do recurso, quando aplicavel. */
|
|
28
|
+
path?: string | null;
|
|
29
|
+
}
|
|
30
|
+
/** Envelope canonico. Publicado em NEXUS_WEBHOOK_EVENTS_TOPIC e entregue
|
|
31
|
+
* como body (JSON) do POST ao assinante. `id` e a chave de idempotencia. */
|
|
32
|
+
export interface INexusWebhookEvent {
|
|
33
|
+
id: string;
|
|
34
|
+
type: NexusWebhookEventType | string;
|
|
35
|
+
api_version: string;
|
|
36
|
+
occurred_at: string;
|
|
37
|
+
actor: INexusWebhookActor;
|
|
38
|
+
resource: INexusWebhookResource;
|
|
39
|
+
/** snapshot fat do recurso + campos do evento (previous_status, etc.). */
|
|
40
|
+
data: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export type NexusWebhookDisabledReason = "circuit_breaker" | "manual" | null;
|
|
43
|
+
export interface INexusWebhookSubscription extends IFireGlobalDoc {
|
|
44
|
+
name: string;
|
|
45
|
+
url: string;
|
|
46
|
+
/** tipos exatos e/ou globs (`tenant.*`, `finops.billing.*`, `*`). */
|
|
47
|
+
events: string[];
|
|
48
|
+
active: boolean;
|
|
49
|
+
/** headers HTTP custom enviados em cada POST (nao inclui a assinatura). */
|
|
50
|
+
headers?: Record<string, string> | null;
|
|
51
|
+
disabled_reason?: NexusWebhookDisabledReason;
|
|
52
|
+
auto_disabled_at?: Date | null;
|
|
53
|
+
consecutive_failures?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface INexusWebhookRotatedSecret {
|
|
56
|
+
secret: string;
|
|
57
|
+
/** apos esta data o secret antigo deixa de ser aceito (janela dupla). */
|
|
58
|
+
expires_at: Date | null;
|
|
59
|
+
}
|
|
60
|
+
/** Subdoc `subscriptions/{id}/private/secret`. Nunca sai da API (retornado
|
|
61
|
+
* so na criacao/rotacao). */
|
|
62
|
+
export interface INexusWebhookSecretDoc {
|
|
63
|
+
secret: string;
|
|
64
|
+
rotated_from?: INexusWebhookRotatedSecret | null;
|
|
65
|
+
created_at?: Date | null;
|
|
66
|
+
updated_at?: Date | null;
|
|
67
|
+
}
|
|
68
|
+
export interface INexusWebhookDeliveryAttempt {
|
|
69
|
+
at: string;
|
|
70
|
+
response_code: number | null;
|
|
71
|
+
error?: string | null;
|
|
72
|
+
duration_ms: number;
|
|
73
|
+
}
|
|
74
|
+
/** Subdoc `subscriptions/{subId}/deliveries/{eventId}` (docId = event id ⇒
|
|
75
|
+
* dedup natural). Estado mutavel; historico completo vai para o BQ. */
|
|
76
|
+
export interface INexusWebhookDelivery {
|
|
77
|
+
event_id: string;
|
|
78
|
+
event_type: string;
|
|
79
|
+
status: NexusWebhookDeliveryStatus;
|
|
80
|
+
attempts: INexusWebhookDeliveryAttempt[];
|
|
81
|
+
last_response_code?: number | null;
|
|
82
|
+
/** envelope integral (re-entregue no replay sem reconstruir). */
|
|
83
|
+
envelope: INexusWebhookEvent;
|
|
84
|
+
created_at?: Date | null;
|
|
85
|
+
updated_at?: Date | null;
|
|
86
|
+
delivered_at?: Date | null;
|
|
87
|
+
}
|
|
88
|
+
/** Mensagem publicada em NEXUS_WEBHOOK_DELIVERIES_TOPIC (fan-out). */
|
|
89
|
+
export interface INexusWebhookDeliveryMessage {
|
|
90
|
+
subscription_id: string;
|
|
91
|
+
envelope: INexusWebhookEvent;
|
|
92
|
+
}
|
|
93
|
+
/** Uma linha por tentativa em `nexus.nex_webhook_delivery_events`. */
|
|
94
|
+
export interface INexusWebhookDeliveryLogEvent {
|
|
95
|
+
event_id: string;
|
|
96
|
+
event_type: string;
|
|
97
|
+
subscription_id: string;
|
|
98
|
+
subscription_name: string;
|
|
99
|
+
status: NexusWebhookDeliveryStatus;
|
|
100
|
+
attempt_number: number;
|
|
101
|
+
response_code: number | null;
|
|
102
|
+
error: string | null;
|
|
103
|
+
duration_ms: number;
|
|
104
|
+
url: string;
|
|
105
|
+
occurred_at: string;
|
|
106
|
+
delivered_at: string;
|
|
107
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Nexus outbound webhooks — canonical event envelope, subscription registry,
|
|
3
|
+
// delivery tracking and BigQuery audit shapes.
|
|
4
|
+
//
|
|
5
|
+
// Regra do repo: `types/` = interfaces TS escritas a mao (sem zod, sem z.infer).
|
|
6
|
+
// A validacao de payload (zod) vive nas rotas do endpoint nex_webhooks.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.NEXUS_WEBHOOK_EVENT_TYPES = exports.NEXUS_WEBHOOK_API_VERSION = exports.NEXUS_WEBHOOKS_PLATFORM_PATH = exports.NEXUS_WEBHOOK_DELIVERY_LOG_TOPIC = exports.NEXUS_WEBHOOK_DELIVERIES_TOPIC = exports.NEXUS_WEBHOOK_EVENTS_TOPIC = void 0;
|
|
9
|
+
// ── Constants ──
|
|
10
|
+
/** Topico central: todo emitNexusEvent() publica aqui (envelope canonico). */
|
|
11
|
+
exports.NEXUS_WEBHOOK_EVENTS_TOPIC = "nexus-webhook-events";
|
|
12
|
+
/** Topico de fan-out: 1 mensagem por (subscription x evento) casado. */
|
|
13
|
+
exports.NEXUS_WEBHOOK_DELIVERIES_TOPIC = "nexus-webhook-deliveries";
|
|
14
|
+
/** Topico de auditoria: 1 mensagem por tentativa de entrega (sink BQ). */
|
|
15
|
+
exports.NEXUS_WEBHOOK_DELIVERY_LOG_TOPIC = "nexus-webhook-delivery-log";
|
|
16
|
+
/** Raiz Firestore do registry (subdocs `private/secret` guardam o segredo). */
|
|
17
|
+
exports.NEXUS_WEBHOOKS_PLATFORM_PATH = "platform/nexus-webhooks";
|
|
18
|
+
/** Versao do contrato do envelope, carimbada em `api_version`. */
|
|
19
|
+
exports.NEXUS_WEBHOOK_API_VERSION = "2026-07-01";
|
|
20
|
+
/** Catalogo v1 de tipos de evento. Alimenta `GET /event-types` e a validacao
|
|
21
|
+
* de filtros das subscriptions (globs sao validados a parte). */
|
|
22
|
+
exports.NEXUS_WEBHOOK_EVENT_TYPES = [
|
|
23
|
+
// tenant (nex-tenants)
|
|
24
|
+
"tenant.created",
|
|
25
|
+
"tenant.updated",
|
|
26
|
+
"tenant.status_changed",
|
|
27
|
+
// finops — customer
|
|
28
|
+
"finops.customer.created",
|
|
29
|
+
"finops.customer.updated",
|
|
30
|
+
"finops.customer.status_changed",
|
|
31
|
+
"finops.customer.deleted",
|
|
32
|
+
// finops — contract
|
|
33
|
+
"finops.contract.created",
|
|
34
|
+
"finops.contract.updated",
|
|
35
|
+
"finops.contract.status_changed",
|
|
36
|
+
"finops.contract.deleted",
|
|
37
|
+
// finops — billing
|
|
38
|
+
"finops.billing.created",
|
|
39
|
+
"finops.billing.updated",
|
|
40
|
+
"finops.billing.status_changed",
|
|
41
|
+
"finops.billing.deleted",
|
|
42
|
+
// finops — invoice (nota fiscal)
|
|
43
|
+
"finops.invoice.created",
|
|
44
|
+
"finops.invoice.updated",
|
|
45
|
+
"finops.invoice.status_changed",
|
|
46
|
+
"finops.invoice.deleted",
|
|
47
|
+
// finops — payment (evento semantico)
|
|
48
|
+
"finops.payment.received",
|
|
49
|
+
// forms (onboarding)
|
|
50
|
+
"forms.onboarding.submitted",
|
|
51
|
+
"forms.onboarding.updated",
|
|
52
|
+
"forms.onboarding.completed",
|
|
53
|
+
];
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
// Nexus outbound webhooks — canonical event envelope, subscription registry,
|
|
2
|
+
// delivery tracking and BigQuery audit shapes.
|
|
3
|
+
//
|
|
4
|
+
// Regra do repo: `types/` = interfaces TS escritas a mao (sem zod, sem z.infer).
|
|
5
|
+
// A validacao de payload (zod) vive nas rotas do endpoint nex_webhooks.
|
|
6
|
+
|
|
7
|
+
import type { IFireGlobalDoc } from "../shared";
|
|
8
|
+
|
|
9
|
+
// ── Constants ──
|
|
10
|
+
|
|
11
|
+
/** Topico central: todo emitNexusEvent() publica aqui (envelope canonico). */
|
|
12
|
+
export const NEXUS_WEBHOOK_EVENTS_TOPIC = "nexus-webhook-events" as const;
|
|
13
|
+
|
|
14
|
+
/** Topico de fan-out: 1 mensagem por (subscription x evento) casado. */
|
|
15
|
+
export const NEXUS_WEBHOOK_DELIVERIES_TOPIC =
|
|
16
|
+
"nexus-webhook-deliveries" as const;
|
|
17
|
+
|
|
18
|
+
/** Topico de auditoria: 1 mensagem por tentativa de entrega (sink BQ). */
|
|
19
|
+
export const NEXUS_WEBHOOK_DELIVERY_LOG_TOPIC =
|
|
20
|
+
"nexus-webhook-delivery-log" as const;
|
|
21
|
+
|
|
22
|
+
/** Raiz Firestore do registry (subdocs `private/secret` guardam o segredo). */
|
|
23
|
+
export const NEXUS_WEBHOOKS_PLATFORM_PATH = "platform/nexus-webhooks" as const;
|
|
24
|
+
|
|
25
|
+
/** Versao do contrato do envelope, carimbada em `api_version`. */
|
|
26
|
+
export const NEXUS_WEBHOOK_API_VERSION = "2026-07-01" as const;
|
|
27
|
+
|
|
28
|
+
// ── Enums / Literals ──
|
|
29
|
+
|
|
30
|
+
export type NexusWebhookActorKind = "user" | "system" | "provider";
|
|
31
|
+
|
|
32
|
+
export type NexusWebhookDeliveryStatus =
|
|
33
|
+
| "pending"
|
|
34
|
+
| "delivered"
|
|
35
|
+
| "failed"
|
|
36
|
+
| "dead_letter";
|
|
37
|
+
|
|
38
|
+
/** Catalogo v1 de tipos de evento. Alimenta `GET /event-types` e a validacao
|
|
39
|
+
* de filtros das subscriptions (globs sao validados a parte). */
|
|
40
|
+
export const NEXUS_WEBHOOK_EVENT_TYPES = [
|
|
41
|
+
// tenant (nex-tenants)
|
|
42
|
+
"tenant.created",
|
|
43
|
+
"tenant.updated",
|
|
44
|
+
"tenant.status_changed",
|
|
45
|
+
// finops — customer
|
|
46
|
+
"finops.customer.created",
|
|
47
|
+
"finops.customer.updated",
|
|
48
|
+
"finops.customer.status_changed",
|
|
49
|
+
"finops.customer.deleted",
|
|
50
|
+
// finops — contract
|
|
51
|
+
"finops.contract.created",
|
|
52
|
+
"finops.contract.updated",
|
|
53
|
+
"finops.contract.status_changed",
|
|
54
|
+
"finops.contract.deleted",
|
|
55
|
+
// finops — billing
|
|
56
|
+
"finops.billing.created",
|
|
57
|
+
"finops.billing.updated",
|
|
58
|
+
"finops.billing.status_changed",
|
|
59
|
+
"finops.billing.deleted",
|
|
60
|
+
// finops — invoice (nota fiscal)
|
|
61
|
+
"finops.invoice.created",
|
|
62
|
+
"finops.invoice.updated",
|
|
63
|
+
"finops.invoice.status_changed",
|
|
64
|
+
"finops.invoice.deleted",
|
|
65
|
+
// finops — payment (evento semantico)
|
|
66
|
+
"finops.payment.received",
|
|
67
|
+
// forms (onboarding)
|
|
68
|
+
"forms.onboarding.submitted",
|
|
69
|
+
"forms.onboarding.updated",
|
|
70
|
+
"forms.onboarding.completed",
|
|
71
|
+
] as const;
|
|
72
|
+
|
|
73
|
+
export type NexusWebhookEventType = (typeof NEXUS_WEBHOOK_EVENT_TYPES)[number];
|
|
74
|
+
|
|
75
|
+
// ── Envelope ──
|
|
76
|
+
|
|
77
|
+
export interface INexusWebhookActor {
|
|
78
|
+
kind: NexusWebhookActorKind;
|
|
79
|
+
/** uid do usuario, nome do sistema, ou nome do provider (asaas/inter/...). */
|
|
80
|
+
id: string | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface INexusWebhookResource {
|
|
84
|
+
/** ex.: 'customer', 'contract', 'billing', 'invoice', 'tenant', 'form'. */
|
|
85
|
+
kind: string;
|
|
86
|
+
id: string;
|
|
87
|
+
/** caminho Firestore do recurso, quando aplicavel. */
|
|
88
|
+
path?: string | null;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Envelope canonico. Publicado em NEXUS_WEBHOOK_EVENTS_TOPIC e entregue
|
|
92
|
+
* como body (JSON) do POST ao assinante. `id` e a chave de idempotencia. */
|
|
93
|
+
export interface INexusWebhookEvent {
|
|
94
|
+
id: string; // evt_<uuid>
|
|
95
|
+
type: NexusWebhookEventType | string;
|
|
96
|
+
api_version: string;
|
|
97
|
+
occurred_at: string; // ISO 8601
|
|
98
|
+
actor: INexusWebhookActor;
|
|
99
|
+
resource: INexusWebhookResource;
|
|
100
|
+
/** snapshot fat do recurso + campos do evento (previous_status, etc.). */
|
|
101
|
+
data: Record<string, unknown>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ── Subscription (registry) ──
|
|
105
|
+
|
|
106
|
+
export type NexusWebhookDisabledReason =
|
|
107
|
+
| "circuit_breaker"
|
|
108
|
+
| "manual"
|
|
109
|
+
| null;
|
|
110
|
+
|
|
111
|
+
export interface INexusWebhookSubscription extends IFireGlobalDoc {
|
|
112
|
+
name: string;
|
|
113
|
+
url: string;
|
|
114
|
+
/** tipos exatos e/ou globs (`tenant.*`, `finops.billing.*`, `*`). */
|
|
115
|
+
events: string[];
|
|
116
|
+
active: boolean;
|
|
117
|
+
/** headers HTTP custom enviados em cada POST (nao inclui a assinatura). */
|
|
118
|
+
headers?: Record<string, string> | null;
|
|
119
|
+
disabled_reason?: NexusWebhookDisabledReason;
|
|
120
|
+
auto_disabled_at?: Date | null;
|
|
121
|
+
consecutive_failures?: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ── Secret (subdoc privado) ──
|
|
125
|
+
|
|
126
|
+
export interface INexusWebhookRotatedSecret {
|
|
127
|
+
secret: string;
|
|
128
|
+
/** apos esta data o secret antigo deixa de ser aceito (janela dupla). */
|
|
129
|
+
expires_at: Date | null;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Subdoc `subscriptions/{id}/private/secret`. Nunca sai da API (retornado
|
|
133
|
+
* so na criacao/rotacao). */
|
|
134
|
+
export interface INexusWebhookSecretDoc {
|
|
135
|
+
secret: string; // whsec_<hex>
|
|
136
|
+
rotated_from?: INexusWebhookRotatedSecret | null;
|
|
137
|
+
created_at?: Date | null;
|
|
138
|
+
updated_at?: Date | null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ── Delivery (subdoc por evento) ──
|
|
142
|
+
|
|
143
|
+
export interface INexusWebhookDeliveryAttempt {
|
|
144
|
+
at: string; // ISO 8601
|
|
145
|
+
response_code: number | null;
|
|
146
|
+
error?: string | null;
|
|
147
|
+
duration_ms: number;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Subdoc `subscriptions/{subId}/deliveries/{eventId}` (docId = event id ⇒
|
|
151
|
+
* dedup natural). Estado mutavel; historico completo vai para o BQ. */
|
|
152
|
+
export interface INexusWebhookDelivery {
|
|
153
|
+
event_id: string;
|
|
154
|
+
event_type: string;
|
|
155
|
+
status: NexusWebhookDeliveryStatus;
|
|
156
|
+
attempts: INexusWebhookDeliveryAttempt[];
|
|
157
|
+
last_response_code?: number | null;
|
|
158
|
+
/** envelope integral (re-entregue no replay sem reconstruir). */
|
|
159
|
+
envelope: INexusWebhookEvent;
|
|
160
|
+
created_at?: Date | null;
|
|
161
|
+
updated_at?: Date | null;
|
|
162
|
+
delivered_at?: Date | null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Mensagem publicada em NEXUS_WEBHOOK_DELIVERIES_TOPIC (fan-out). */
|
|
166
|
+
export interface INexusWebhookDeliveryMessage {
|
|
167
|
+
subscription_id: string;
|
|
168
|
+
envelope: INexusWebhookEvent;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// ── Delivery log (sink BQ) ──
|
|
172
|
+
|
|
173
|
+
/** Uma linha por tentativa em `nexus.nex_webhook_delivery_events`. */
|
|
174
|
+
export interface INexusWebhookDeliveryLogEvent {
|
|
175
|
+
event_id: string;
|
|
176
|
+
event_type: string;
|
|
177
|
+
subscription_id: string;
|
|
178
|
+
subscription_name: string;
|
|
179
|
+
status: NexusWebhookDeliveryStatus;
|
|
180
|
+
attempt_number: number;
|
|
181
|
+
response_code: number | null;
|
|
182
|
+
error: string | null;
|
|
183
|
+
duration_ms: number;
|
|
184
|
+
url: string;
|
|
185
|
+
occurred_at: string; // ISO 8601 — do envelope (particionamento BQ)
|
|
186
|
+
delivered_at: string; // ISO 8601 — momento da tentativa
|
|
187
|
+
}
|