@hostwebhook/platform-contracts 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +64 -4
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +2 -0
  4. package/dist/operadores.d.ts +60 -0
  5. package/dist/operadores.js +123 -0
  6. package/dist/servicios/almacenes-vectoriales.d.ts +105 -0
  7. package/dist/servicios/almacenes-vectoriales.js +26 -0
  8. package/dist/servicios/aprobaciones-pendientes.d.ts +207 -0
  9. package/dist/servicios/aprobaciones-pendientes.js +51 -0
  10. package/dist/servicios/avisos-en-vivo.d.ts +106 -0
  11. package/dist/servicios/avisos-en-vivo.js +60 -0
  12. package/dist/servicios/canal-de-stream.d.ts +78 -0
  13. package/dist/servicios/canal-de-stream.js +5 -0
  14. package/dist/servicios/conversaciones-del-chat.d.ts +139 -0
  15. package/dist/servicios/conversaciones-del-chat.js +51 -0
  16. package/dist/servicios/corridas-programadas.d.ts +29 -0
  17. package/dist/servicios/corridas-programadas.js +5 -0
  18. package/dist/servicios/credencial/permiso-sobre-credencial.d.ts +61 -0
  19. package/dist/servicios/credencial/permiso-sobre-credencial.js +42 -0
  20. package/dist/servicios/credenciales-del-gateway.d.ts +722 -0
  21. package/dist/servicios/credenciales-del-gateway.js +114 -0
  22. package/dist/servicios/cuentas-de-atlassian.d.ts +22 -0
  23. package/dist/servicios/cuentas-de-atlassian.js +5 -0
  24. package/dist/servicios/descarga-de-drive.d.ts +74 -0
  25. package/dist/servicios/descarga-de-drive.js +41 -0
  26. package/dist/servicios/ejecucion-de-ia.d.ts +81 -0
  27. package/dist/servicios/ejecucion-de-ia.js +39 -0
  28. package/dist/servicios/enlaces-de-flujo.d.ts +59 -0
  29. package/dist/servicios/enlaces-de-flujo.js +27 -0
  30. package/dist/servicios/ficheros-del-gateway.d.ts +210 -0
  31. package/dist/servicios/ficheros-del-gateway.js +8 -0
  32. package/dist/servicios/formas-compartidas.d.ts +57 -0
  33. package/dist/servicios/formas-compartidas.js +22 -0
  34. package/dist/servicios/historial-de-corridas.d.ts +75 -0
  35. package/dist/servicios/historial-de-corridas.js +7 -0
  36. package/dist/servicios/index.d.ts +57 -0
  37. package/dist/servicios/index.js +44 -0
  38. package/dist/servicios/limites-del-plan.d.ts +82 -0
  39. package/dist/servicios/limites-del-plan.js +41 -0
  40. package/dist/servicios/motor-de-ejecucion.d.ts +197 -0
  41. package/dist/servicios/motor-de-ejecucion.js +11 -0
  42. package/dist/servicios/plantillas-de-origen.d.ts +25 -0
  43. package/dist/servicios/plantillas-de-origen.js +5 -0
  44. package/dist/servicios/posts-sociales.d.ts +69 -0
  45. package/dist/servicios/posts-sociales.js +23 -0
  46. package/dist/servicios/registro-de-entregas.d.ts +93 -0
  47. package/dist/servicios/registro-de-entregas.js +46 -0
  48. package/dist/servicios/registro-de-eventos.d.ts +135 -0
  49. package/dist/servicios/registro-de-eventos.js +62 -0
  50. package/dist/servicios/restauracion-de-nodos.d.ts +53 -0
  51. package/dist/servicios/restauracion-de-nodos.js +4 -0
  52. package/dist/servicios/salud-del-webhook.d.ts +26 -0
  53. package/dist/servicios/salud-del-webhook.js +6 -0
  54. package/dist/servicios/secretos-de-firma.d.ts +26 -0
  55. package/dist/servicios/secretos-de-firma.js +5 -0
  56. package/dist/servicios/telemetria.d.ts +114 -0
  57. package/dist/servicios/telemetria.js +60 -0
  58. package/dist/servicios/trazas-de-llm.d.ts +79 -0
  59. package/dist/servicios/trazas-de-llm.js +23 -0
  60. package/dist/servicios/tuneles.d.ts +106 -0
  61. package/dist/servicios/tuneles.js +87 -0
  62. package/dist/servicios/workspace/acceso-al-recurso.d.ts +39 -0
  63. package/dist/servicios/workspace/acceso-al-recurso.js +5 -0
  64. package/dist/servicios/zona-horaria-del-usuario.d.ts +40 -0
  65. package/dist/servicios/zona-horaria-del-usuario.js +7 -0
  66. package/package.json +9 -3
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALMACEN_DE_OBJETOS = exports.REGISTRO_DE_FICHEROS = void 0;
4
+ /**
5
+ * ⚠️ Cadenas y no `Symbol`, igual que el resto de tokens de la Fase 2.
6
+ */
7
+ exports.REGISTRO_DE_FICHEROS = 'REGISTRO_DE_FICHEROS';
8
+ exports.ALMACEN_DE_OBJETOS = 'ALMACEN_DE_OBJETOS';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Las formas que varios contratos de esta carpeta necesitan, y que antes
3
+ * vivían fuera de ella.
4
+ *
5
+ * ## Por qué están aquí y no donde estaban
6
+ *
7
+ * Al sacar los contratos del monolito, tres de ellos apuntaban a tipos que se
8
+ * quedaban en la api o en el SDK. Un contrato que describe una frontera no
9
+ * puede depender de un lado de esa frontera: si `RegistroDeFicheros` habla de
10
+ * un `FileRef`, entonces `FileRef` **es parte del contrato**, no un detalle
11
+ * del gateway.
12
+ *
13
+ * Los tres eran `import type`, así que no había ciclo en tiempo de ejecución —
14
+ * pero sí en el de compilación, y sobre todo una mentira sobre quién define
15
+ * qué.
16
+ *
17
+ * ⚠️ Los originales pasan a re-exportar desde aquí. Copiarlos habría dejado dos
18
+ * definiciones que un día se escriben distinto, que es exactamente lo que este
19
+ * paquete existe para impedir.
20
+ */
21
+ /** Un fichero ya registrado: lo que un nodo recibe para poder leerlo. */
22
+ export interface FileRef {
23
+ id: string;
24
+ key: string;
25
+ originalName: string;
26
+ mimeType: string;
27
+ size: number;
28
+ downloadUrl: string;
29
+ }
30
+ export type ChunkingStrategy = 'recursive' | 'fixed' | 'semantic';
31
+ /**
32
+ * `skipped` es un estado de primera y no un `failed` descafeinado: un paso que
33
+ * no llegó a correr porque el anterior falló no es lo mismo que uno que sí
34
+ * corrió y salió mal, y la pantalla necesita distinguirlos para enseñar dónde
35
+ * se cortó el flujo.
36
+ */
37
+ export type RunStepStatus = 'success' | 'failed' | 'skipped';
38
+ export interface PasoEjecutado {
39
+ organizationId: string;
40
+ correlationId: string;
41
+ nodeId: string;
42
+ nodeName?: string;
43
+ nodeType?: string;
44
+ status: RunStepStatus;
45
+ startedAt: Date;
46
+ durationMs: number;
47
+ error?: string;
48
+ /** El origen de la corrida, para poder abrirla en la primera fila. */
49
+ sourceId?: string;
50
+ sourceName?: string;
51
+ workspaceId?: string;
52
+ entrada?: unknown;
53
+ salida?: unknown;
54
+ metadata?: Record<string, unknown>;
55
+ /** Cómo se disparó la corrida. Ausente = producción. */
56
+ modo?: 'pipeline';
57
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * Las formas que varios contratos de esta carpeta necesitan, y que antes
4
+ * vivían fuera de ella.
5
+ *
6
+ * ## Por qué están aquí y no donde estaban
7
+ *
8
+ * Al sacar los contratos del monolito, tres de ellos apuntaban a tipos que se
9
+ * quedaban en la api o en el SDK. Un contrato que describe una frontera no
10
+ * puede depender de un lado de esa frontera: si `RegistroDeFicheros` habla de
11
+ * un `FileRef`, entonces `FileRef` **es parte del contrato**, no un detalle
12
+ * del gateway.
13
+ *
14
+ * Los tres eran `import type`, así que no había ciclo en tiempo de ejecución —
15
+ * pero sí en el de compilación, y sobre todo una mentira sobre quién define
16
+ * qué.
17
+ *
18
+ * ⚠️ Los originales pasan a re-exportar desde aquí. Copiarlos habría dejado dos
19
+ * definiciones que un día se escriben distinto, que es exactamente lo que este
20
+ * paquete existe para impedir.
21
+ */
22
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,75 @@
1
+ import type { PasoEjecutado as PasoDelSdk } from './formas-compartidas';
2
+ /**
3
+ * Lo que un nodo apunta en el historial de corridas. Dos cosas.
4
+ *
5
+ * ## Por qué
6
+ *
7
+ * Costura de la Fase 2. `nodes/` y `common/` importaban `history-runs/` así:
8
+ *
9
+ * 6 `HistoryRecorderService` el grabador
10
+ * 3 `paso-de-origen` un ayudante PURO, que se muda con ellos
11
+ * 5 `history-runs.module` cableado, desaparece con la mudanza
12
+ *
13
+ * `HistoryRecorderService` arrastra cuatro colecciones —`runs`, `run_steps`,
14
+ * `run_payloads`, `flow_versions`—, **su propia conexión de Mongo** a otra
15
+ * base, el almacén de payloads que se van a R2 y el sellado de versiones del
16
+ * flujo contra el lienzo. El historial es del gateway: es lo que la pantalla
17
+ * lee. El nodo sólo tiene que decir qué hizo.
18
+ *
19
+ * ## Dos métodos, y ya estaban medio declarados
20
+ *
21
+ * El SDK ya tiene `RegistradorDeHistorial` con `registrarPaso`, porque el
22
+ * ciclo de vida lo necesitaba y no podía depender de la api. Le falta
23
+ * `cerrar`, que es lo que usa quien ARRANCA una corrida y sabe cuándo acaba.
24
+ *
25
+ * Así que este contrato no inventa: reusa `PasoEjecutado` del SDK y le añade
26
+ * el único campo que la api tiene de más.
27
+ *
28
+ * ⚠️ Las dos definiciones habían divergido — la del SDK tiene `metadata` y le
29
+ * falta `esOrigen`; la de la api al revés. `extends` deja de multiplicar
30
+ * copias: los campos compartidos se declaran en un sitio.
31
+ *
32
+ * ## Cómo viaja
33
+ *
34
+ * ⚠️ Los dos métodos devuelven `void` y **no esperan ni lanzan**: por dentro
35
+ * hacen `void this.encolar(...).catch(...)`. Eso es deliberado y hay que
36
+ * conservarlo. Un nodo no puede fallar porque no se haya podido escribir una
37
+ * fila de historial, y menos aún quedarse esperando a que se escriba —
38
+ * `registrarPaso` corre en el camino caliente de CADA paso del pipeline.
39
+ *
40
+ * ⚠️ Y el orden importa: el grabador encola por `correlationId` para que los
41
+ * pasos de una corrida se escriban en orden y `cerrar` llegue el último. Una
42
+ * implementación por red que mandara los mensajes en paralelo cerraría
43
+ * corridas antes de tiempo, y el veredicto saldría mal.
44
+ */
45
+ /**
46
+ * Un paso ejecutado.
47
+ *
48
+ * ⚠️ Extiende el del SDK en vez de copiarlo. `esOrigen` es lo único que la api
49
+ * necesita de más: marca el nodo que ARRANCÓ la corrida, que cuenta en
50
+ * `steps` pero no en el denominador del veredicto. Sin él, una corrida de una
51
+ * sola acción fallida se lee `partial` en vez de `failed`.
52
+ */
53
+ export interface PasoEjecutado extends PasoDelSdk {
54
+ esOrigen?: boolean;
55
+ }
56
+ /** Quien anota lo que pasa en una corrida. */
57
+ export interface GrabadorDeHistorial {
58
+ /**
59
+ * ⚠️ `void`, no espera y no lanza. Corre en el camino caliente de cada
60
+ * paso: ver la nota de arriba.
61
+ */
62
+ registrarPaso(paso: PasoEjecutado): void;
63
+ /**
64
+ * La corrida terminó.
65
+ *
66
+ * ⚠️ Tiene que llegar DESPUÉS de los pasos de esa misma `correlationId`. El
67
+ * grabador lo garantiza encolando por corrida; quien lo implemente por red
68
+ * tiene que garantizarlo también.
69
+ */
70
+ cerrar(correlationId: string): void;
71
+ }
72
+ /**
73
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
74
+ */
75
+ export declare const HISTORIAL_DE_CORRIDAS = "HISTORIAL_DE_CORRIDAS";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HISTORIAL_DE_CORRIDAS = void 0;
4
+ /**
5
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
6
+ */
7
+ exports.HISTORIAL_DE_CORRIDAS = 'HISTORIAL_DE_CORRIDAS';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Los contratos entre servicios: lo que el gateway y hw-nodes se piden.
3
+ *
4
+ * Cada fichero es **un token de cadena + la interfaz que ese token promete**.
5
+ * Nada de implementación: quien sirve el contrato vive en un servicio y quien
6
+ * lo consume en el otro, y este paquete es lo único que los dos comparten.
7
+ *
8
+ * ## Por qué aquí y no en `@hostwebhook/node-sdk`
9
+ *
10
+ * El SDK está **publicado para autores de nodos**: es ciclo de vida,
11
+ * reintentos, filtros e iteración. Estos veintiocho son fontanería interna
12
+ * entre dos servicios nuestros —`TUNELES_DE_LA_ORGANIZACION`,
13
+ * `SECRETOS_DE_FIRMA`, `REGISTRO_DE_ENTREGAS`—, y meterlos ahí los habría
14
+ * convertido en API pública: cada cambio pasaría a ser una pregunta de
15
+ * compatibilidad hacia fuera.
16
+ *
17
+ * ## ⚠️ Lo que NO entra aquí
18
+ *
19
+ * Lo mismo que dice el `index.ts` de arriba, y con un caso que se comprobó al
20
+ * mudarlos: `limites-del-plan` entra porque es la PREGUNTA («¿cuáles son los
21
+ * topes de esta organización?»), no los topes. Los valores —`PLAN_LIMITS`, los
22
+ * precios, los ids de Stripe— se quedan en el gateway, donde se pueden cambiar
23
+ * sin publicar un paquete.
24
+ *
25
+ * Y `credenciales-del-gateway` entra porque describe la forma de la pregunta,
26
+ * que está diseñada justo para que los secretos NO crucen a lo bruto. Ningún
27
+ * secreto vive aquí.
28
+ */
29
+ export type { FileRef, ChunkingStrategy, RunStepStatus, PasoEjecutado as PasoEjecutadoDelSdk, } from './formas-compartidas';
30
+ export * from './almacenes-vectoriales';
31
+ export * from './aprobaciones-pendientes';
32
+ export * from './avisos-en-vivo';
33
+ export * from './canal-de-stream';
34
+ export * from './conversaciones-del-chat';
35
+ export * from './corridas-programadas';
36
+ export * from './credencial/permiso-sobre-credencial';
37
+ export * from './credenciales-del-gateway';
38
+ export * from './cuentas-de-atlassian';
39
+ export * from './descarga-de-drive';
40
+ export * from './ejecucion-de-ia';
41
+ export * from './enlaces-de-flujo';
42
+ export * from './ficheros-del-gateway';
43
+ export * from './historial-de-corridas';
44
+ export * from './limites-del-plan';
45
+ export * from './motor-de-ejecucion';
46
+ export * from './plantillas-de-origen';
47
+ export * from './posts-sociales';
48
+ export * from './registro-de-entregas';
49
+ export * from './registro-de-eventos';
50
+ export * from './restauracion-de-nodos';
51
+ export * from './salud-del-webhook';
52
+ export * from './secretos-de-firma';
53
+ export * from './telemetria';
54
+ export * from './trazas-de-llm';
55
+ export * from './tuneles';
56
+ export * from './workspace/acceso-al-recurso';
57
+ export * from './zona-horaria-del-usuario';
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./almacenes-vectoriales"), exports);
18
+ __exportStar(require("./aprobaciones-pendientes"), exports);
19
+ __exportStar(require("./avisos-en-vivo"), exports);
20
+ __exportStar(require("./canal-de-stream"), exports);
21
+ __exportStar(require("./conversaciones-del-chat"), exports);
22
+ __exportStar(require("./corridas-programadas"), exports);
23
+ __exportStar(require("./credencial/permiso-sobre-credencial"), exports);
24
+ __exportStar(require("./credenciales-del-gateway"), exports);
25
+ __exportStar(require("./cuentas-de-atlassian"), exports);
26
+ __exportStar(require("./descarga-de-drive"), exports);
27
+ __exportStar(require("./ejecucion-de-ia"), exports);
28
+ __exportStar(require("./enlaces-de-flujo"), exports);
29
+ __exportStar(require("./ficheros-del-gateway"), exports);
30
+ __exportStar(require("./historial-de-corridas"), exports);
31
+ __exportStar(require("./limites-del-plan"), exports);
32
+ __exportStar(require("./motor-de-ejecucion"), exports);
33
+ __exportStar(require("./plantillas-de-origen"), exports);
34
+ __exportStar(require("./posts-sociales"), exports);
35
+ __exportStar(require("./registro-de-entregas"), exports);
36
+ __exportStar(require("./registro-de-eventos"), exports);
37
+ __exportStar(require("./restauracion-de-nodos"), exports);
38
+ __exportStar(require("./salud-del-webhook"), exports);
39
+ __exportStar(require("./secretos-de-firma"), exports);
40
+ __exportStar(require("./telemetria"), exports);
41
+ __exportStar(require("./trazas-de-llm"), exports);
42
+ __exportStar(require("./tuneles"), exports);
43
+ __exportStar(require("./workspace/acceso-al-recurso"), exports);
44
+ __exportStar(require("./zona-horaria-del-usuario"), exports);
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Los topes del plan que un nodo necesita saber. Nada más.
3
+ *
4
+ * ## Por qué
5
+ *
6
+ * Costura de la Fase 2. `src/nodes/` importaba `plans/` 64 veces, y ese
7
+ * número engaña como engañaban los otros:
8
+ *
9
+ * 48 `PlansModule` cableado de DI, desaparece con la mudanza
10
+ * 13 `PlansService` de los que TODOS llaman UN método
11
+ * 3 helpers sueltos `managedStorageUsage`, `enMegas`, `registerManagedStore`
12
+ *
13
+ * Los trece llaman `getOrgPlanLimits` y ninguno llama nada más. `PlansService`
14
+ * arrastra 13 ficheros del gateway —`plan.constants`, la entidad de usuario,
15
+ * la de organización— y con eso esos trece servicios de nodo no se pueden
16
+ * mudar a `hw-nodes`.
17
+ *
18
+ * ## Lo que lee cada uno, medido
19
+ *
20
+ * Del resultado se desestructura `{ limits, tier }`, y de `limits` se leen
21
+ * SEIS campos. Son los que están abajo. No se copia la forma entera de
22
+ * `PLAN_LIMITS` —que tiene muchos más— por la misma doctrina que el resto de
23
+ * contratos de esta fase: la superficie USADA, no la entidad completa.
24
+ *
25
+ * ⚠️ Y aquí el compilador es el verificador. Si me dejé un campo fuera, el
26
+ * sitio que lo lee no compila — no hace falta creerse la medición.
27
+ *
28
+ * ## Cuando esto cruce una red
29
+ *
30
+ * Bien: son números y una cadena. A diferencia de la costura del motor —que
31
+ * pasaba documentos de Mongoose vivos— y de la de Drive —donde `auth` es un
32
+ * objeto con métodos—, esto viaja tal cual.
33
+ */
34
+ /** Los topes que un nodo consulta antes de aceptar una configuración. */
35
+ export interface TopesDelPlan {
36
+ /** Reintentos máximos de una entrega. */
37
+ maxRetries: number;
38
+ /** Segundos entre reintentos. */
39
+ maxRetryDelaySeconds: number;
40
+ /**
41
+ * El TECHO del backoff, que no es lo mismo que el de arriba.
42
+ *
43
+ * ⚠️ Octavo campo, y otra vez lo encontró el COMPILADOR y no mi medición.
44
+ * Se parecen tanto en el nombre que es fácil dar uno por el otro: uno es el
45
+ * hueco entre reintentos y éste el límite al que el backoff deja de crecer.
46
+ * Confundirlos hace que una organización reintente con el calendario de
47
+ * otra, y nada lo dice.
48
+ */
49
+ maxRetryDelayCapSeconds: number;
50
+ /** Techo del nodo de espera. */
51
+ maxDelaySeconds: number;
52
+ /** Minutos que puede esperar una aprobación. */
53
+ maxApprovalTimeoutMinutes: number;
54
+ /** Minutos que puede esperar un merge a sus ramas. */
55
+ maxMergeTimeoutMinutes: number;
56
+ /** Cada cuánto, como mínimo, puede dispararse un cron. */
57
+ minCronIntervalMinutes: number;
58
+ /**
59
+ * Cuántas veces puede pasar una corrida por el mismo nodo.
60
+ *
61
+ * ⚠️ Éste se me escapó al medir y lo encontró el COMPILADOR: se lee con
62
+ * encadenado opcional (`?.limits?.maxNodeCycles`) y mi barrido exigía un
63
+ * punto literal. Es la cuarta forma del mismo error esta tanda —dar por
64
+ * hecho que el código se escribe como uno lo busca— y por eso el contrato
65
+ * se escribe primero y se deja que tsc lo corrija, en vez de fiarse de la
66
+ * medición.
67
+ */
68
+ maxNodeCycles: number;
69
+ }
70
+ export interface LimitesDeLaOrganizacion {
71
+ limits: TopesDelPlan;
72
+ /** El plan contratado. Se usa para el mensaje de error, no para decidir. */
73
+ tier: string;
74
+ }
75
+ export interface LimitesDelPlan {
76
+ getOrgPlanLimits(orgId: string): Promise<LimitesDeLaOrganizacion>;
77
+ }
78
+ /**
79
+ * ⚠️ Cadena y no `Symbol`, igual que los otros tokens de la Fase 2: un
80
+ * `Symbol` no sobrevive a una frontera de módulo duplicada.
81
+ */
82
+ export declare const LIMITES_DEL_PLAN = "LIMITES_DEL_PLAN";
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ /**
3
+ * Los topes del plan que un nodo necesita saber. Nada más.
4
+ *
5
+ * ## Por qué
6
+ *
7
+ * Costura de la Fase 2. `src/nodes/` importaba `plans/` 64 veces, y ese
8
+ * número engaña como engañaban los otros:
9
+ *
10
+ * 48 `PlansModule` cableado de DI, desaparece con la mudanza
11
+ * 13 `PlansService` de los que TODOS llaman UN método
12
+ * 3 helpers sueltos `managedStorageUsage`, `enMegas`, `registerManagedStore`
13
+ *
14
+ * Los trece llaman `getOrgPlanLimits` y ninguno llama nada más. `PlansService`
15
+ * arrastra 13 ficheros del gateway —`plan.constants`, la entidad de usuario,
16
+ * la de organización— y con eso esos trece servicios de nodo no se pueden
17
+ * mudar a `hw-nodes`.
18
+ *
19
+ * ## Lo que lee cada uno, medido
20
+ *
21
+ * Del resultado se desestructura `{ limits, tier }`, y de `limits` se leen
22
+ * SEIS campos. Son los que están abajo. No se copia la forma entera de
23
+ * `PLAN_LIMITS` —que tiene muchos más— por la misma doctrina que el resto de
24
+ * contratos de esta fase: la superficie USADA, no la entidad completa.
25
+ *
26
+ * ⚠️ Y aquí el compilador es el verificador. Si me dejé un campo fuera, el
27
+ * sitio que lo lee no compila — no hace falta creerse la medición.
28
+ *
29
+ * ## Cuando esto cruce una red
30
+ *
31
+ * Bien: son números y una cadena. A diferencia de la costura del motor —que
32
+ * pasaba documentos de Mongoose vivos— y de la de Drive —donde `auth` es un
33
+ * objeto con métodos—, esto viaja tal cual.
34
+ */
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.LIMITES_DEL_PLAN = void 0;
37
+ /**
38
+ * ⚠️ Cadena y no `Symbol`, igual que los otros tokens de la Fase 2: un
39
+ * `Symbol` no sobrevive a una frontera de módulo duplicada.
40
+ */
41
+ exports.LIMITES_DEL_PLAN = 'LIMITES_DEL_PLAN';
@@ -0,0 +1,197 @@
1
+ import type { Types } from 'mongoose';
2
+ /**
3
+ * Lo que un nodo le pide al motor de ejecución. Nada más.
4
+ *
5
+ * ## Por qué existe
6
+ *
7
+ * Es la costura de la Fase 2. Para que `src/nodes/` pueda salir a `hw-nodes`
8
+ * —un servicio aparte— no puede importar `EventPipelineService` ni
9
+ * `PipelineRunService`: son el motor, y el motor se queda en el gateway.
10
+ *
11
+ * Medido antes de escribir esto: son **14 imports en 12 ficheros**, y todo lo
12
+ * que se llama son **seis métodos**. Nada más. Cinco familias de nodo
13
+ * —approval, merge, scheduled-workflows, triggers y ai— y ninguna otra.
14
+ *
15
+ * ⚠️ El barrido que lo midió tuvo que admitir SALTOS DE LÍNEA: en
16
+ * `ai-nodes.service` la llamada está partida
17
+ * (`void this.eventPipelineService` y `.dispatchFromOriginEntity(` debajo),
18
+ * y una regex de una línea se dejó ese método fuera. Una interfaz a la que
19
+ * le falta un método es una interfaz que no sirve.
20
+ *
21
+ * ## Por qué está aquí y no en el SDK
22
+ *
23
+ * Porque todavía no hay un segundo consumidor. El propio plan lo dice para
24
+ * los paquetes: extraer antes de que alguien lo pida es cómo se acaba con
25
+ * código publicado que nadie usa. Cuando `hw-nodes` exista de verdad, este
26
+ * fichero se muda entero y los `import type` de abajo se convierten en las
27
+ * formas planas que viajen por la red.
28
+ *
29
+ * Lo que SÍ cambia hoy es lo que importa: `nodes/` deja de conocer al motor.
30
+ * Los tipos entran por `import type` —que se borra al compilar— y el único
31
+ * vínculo en ejecución es el token, que es una cadena.
32
+ *
33
+ * ## ⚠️ Lo que esta interfaz NO arregla
34
+ *
35
+ * Por aquí cruzan **documentos de Mongoose vivos**, no datos planos:
36
+ * `PendingApprovalDocument`, `WebhookDocument`, `PipelineContext`. El plan
37
+ * dice que `hw-nodes` será «sin estado: el runner le manda entidad, payload
38
+ * y credencial», y eso hoy no es cierto en esta costura. Aplanarlo es
39
+ * trabajo aparte y hay que hacerlo ANTES de que esto cruce una red — un
40
+ * documento de Mongoose no sobrevive a un `JSON.stringify` con sus métodos.
41
+ *
42
+ * Se declaran como formas mínimas y no como las entidades enteras, que es la
43
+ * misma doctrina de `contratos.ts` en el SDK: la superficie USADA, no el
44
+ * documento completo. Así el día que esto se serialice, lo que hay que
45
+ * aplanar está escrito aquí y no hay que ir a buscarlo.
46
+ */
47
+ /**
48
+ * Medido, no adivinado: cada forma de aquí es lo que el motor LEE de ese
49
+ * parámetro y nada más. `webhook` son dos campos, no un documento.
50
+ *
51
+ * ## Por qué son formas y no `unknown`
52
+ *
53
+ * La primera versión los dejó opacos, y opaco no sirve para el destino: el
54
+ * día que esto cruce una red hay que saber QUÉ serializar. Escrito aquí, la
55
+ * lista de lo que hay que empaquetar está donde se necesita.
56
+ *
57
+ * ⚠️ Y NO llevan `[k: string]: unknown`. Un índice de cadena hace la forma
58
+ * MÁS estricta, no menos —un documento de Mongoose no lo tiene— y rechazaría
59
+ * justo lo que hoy se le pasa. Sin él, el tipado estructural acepta el
60
+ * documento vivo Y el objeto plano, que es exactamente lo que hace falta
61
+ * durante la transición.
62
+ *
63
+ * ## Cómo se comprobó que se puede aplanar
64
+ *
65
+ * Se midió qué hace el motor con cada uno: **sólo lecturas de propiedad**,
66
+ * ninguna llamada a método de Mongoose. Y de las siete funciones que reciben
67
+ * uno entero, seis tampoco los tocan. La única que sí —`gateApproval`, con
68
+ * `event.toJSON()`— se arregló para aceptar los dos.
69
+ */
70
+ /** Lo que el motor lee de un evento. */
71
+ export interface EventoDeCorrida {
72
+ id: unknown;
73
+ correlationId?: unknown;
74
+ eventType?: unknown;
75
+ headers?: unknown;
76
+ sourceIp?: unknown;
77
+ webhookId?: unknown;
78
+ }
79
+ /** Y de un webhook: dos campos. */
80
+ export interface WebhookDeCorrida {
81
+ id: unknown;
82
+ name?: unknown;
83
+ }
84
+ /**
85
+ * El contexto de la corrida.
86
+ *
87
+ * ⚠️ `nodeVisitCounts` va como OBJETO y no como `Map`, y ése era el segundo
88
+ * bloqueo del aplanado: un `Map` se convierte en `{}` al serializar, y aquí
89
+ * además se MUTA al otro lado —`ctx.nodeVisitCounts.set(...)`—, así que por
90
+ * una red el contador de ciclos dejaría de contar en silencio. Y fallar en la
91
+ * detección de ciclos es un bucle infinito, no un aviso.
92
+ *
93
+ * No hay que inventar nada: el motor YA hace esta conversión para cruzar la
94
+ * cola de BullMQ —`Object.fromEntries` al salir, `new Map(Object.entries(…))`
95
+ * al entrar, ver `delivery.processor`— porque un job es JSON. La costura usa
96
+ * la misma forma serializada, y el motor convierte en su borde.
97
+ */
98
+ export interface ContextoDeCorrida {
99
+ orgId: string;
100
+ backoffCapMs?: number;
101
+ maxNodeCycles?: number;
102
+ nodeVisitCounts?: Record<string, number>;
103
+ }
104
+ /** Una espera pendiente, de lo que el motor le lee. */
105
+ export interface EsperaPendiente {
106
+ id?: unknown;
107
+ eventId?: unknown;
108
+ eventHeaders?: unknown;
109
+ organizationId?: unknown;
110
+ payload?: unknown;
111
+ pipelineContext?: unknown;
112
+ webhookId?: unknown;
113
+ }
114
+ /** Un nodo de aprobación. */
115
+ export interface NodoDeAprobacion {
116
+ _id: unknown;
117
+ name?: unknown;
118
+ outputNodes?: unknown;
119
+ rejectionOutputNodes?: unknown;
120
+ }
121
+ /** El estado acumulado de un merge. */
122
+ export interface EstadoDeMerge {
123
+ correlationId?: unknown;
124
+ expectedCount?: unknown;
125
+ organizationId?: unknown;
126
+ receivedBranches?: unknown;
127
+ }
128
+ /** Un nodo de merge. */
129
+ export interface NodoDeMerge {
130
+ _id: unknown;
131
+ name?: unknown;
132
+ }
133
+ /** Un paso ejecutado, tal como lo devuelve `resumeFromApproval`. */
134
+ export type PasoDeCorrida = unknown;
135
+ /**
136
+ * Los seis métodos, agrupados por lo que hacen.
137
+ *
138
+ * Se separan en dos interfaces porque hoy las implementan DOS servicios
139
+ * distintos —`EventPipelineService` y `PipelineRunService`— y juntarlas
140
+ * obligaría a un adaptador que no aporta nada.
141
+ */
142
+ export interface DespachoDelMotor {
143
+ /** Sigue el flujo hacia los nodos de salida de un webhook. */
144
+ dispatchOutputNodes(outputNodes: Array<{
145
+ nodeType: string;
146
+ nodeId: Types.ObjectId;
147
+ }>, payload: Record<string, unknown>, event: EventoDeCorrida, webhook: WebhookDeCorrida, ctx: ContextoDeCorrida, depth: number): Promise<void>;
148
+ /**
149
+ * Arranca una corrida desde un nodo cualquiera, sin webhook de por medio.
150
+ * Lo usa el nodo de IA cuando lo dispara un chat: `executeForEvent` se
151
+ * salta el paso de aguas abajo del ciclo de vida, así que hay que
152
+ * empujarlo a mano.
153
+ */
154
+ dispatchFromOriginEntity(params: {
155
+ originType: string;
156
+ originEntity: unknown;
157
+ payload: Record<string, unknown>;
158
+ orgId: string;
159
+ [k: string]: unknown;
160
+ }): Promise<unknown>;
161
+ /** Reanuda tras un visto bueno o un rechazo. */
162
+ resumeAfterApproval(pending: EsperaPendiente, approvalNode: NodoDeAprobacion, action: 'approve' | 'reject'): Promise<void>;
163
+ /** Reanuda tras una respuesta de «envía y espera». */
164
+ resumeAfterSendAndWait(pending: EsperaPendiente, decision: {
165
+ approved: boolean;
166
+ decidedAt: Date;
167
+ decidedBy?: string;
168
+ ipAddress?: string;
169
+ comment?: string;
170
+ [k: string]: unknown;
171
+ }): Promise<void>;
172
+ /** Reanuda cuando a un merge se le acaba el tiempo de espera. */
173
+ resumeAfterMergeTimeout(mergeState: EstadoDeMerge, mergeNode: NodoDeMerge): Promise<void>;
174
+ }
175
+ /** El otro servicio: la corrida de prueba desde el panel. */
176
+ export interface CorridaDelMotor {
177
+ /**
178
+ * Arrancar una corrida desde un nodo de origen.
179
+ *
180
+ * ⚠️ Es «lanza y olvida»: el llamante genera el `executionId`, lo devuelve al
181
+ * panel de inmediato y el progreso viaja por socket. La promesa que sale de
182
+ * aquí NO se espera — esperarla dejaría al navegador colgado el tiempo que
183
+ * dure el flujo entero.
184
+ */
185
+ ejecutar(startNodeType: string, startNodeId: string, payload: Record<string, unknown> | undefined, orgId: string, userId: string, executionId: string): Promise<unknown>;
186
+ resumeFromApproval(approvalNode: NodoDeAprobacion, payload: Record<string, unknown>, action: 'approve' | 'reject', orgId: string): Promise<{
187
+ executionId: string;
188
+ steps: PasoDeCorrida[];
189
+ }>;
190
+ }
191
+ /**
192
+ * ⚠️ Son cadenas y no `Symbol` a propósito: un `Symbol` no sobrevive a un
193
+ * `JSON.stringify` ni a una frontera de módulo duplicada, y esto está
194
+ * pensado para acabar cruzando una.
195
+ */
196
+ export declare const DESPACHO_DEL_MOTOR = "DESPACHO_DEL_MOTOR";
197
+ export declare const CORRIDA_DEL_MOTOR = "CORRIDA_DEL_MOTOR";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CORRIDA_DEL_MOTOR = exports.DESPACHO_DEL_MOTOR = void 0;
4
+ /* ── Los tokens ──────────────────────────────────────────────────── */
5
+ /**
6
+ * ⚠️ Son cadenas y no `Symbol` a propósito: un `Symbol` no sobrevive a un
7
+ * `JSON.stringify` ni a una frontera de módulo duplicada, y esto está
8
+ * pensado para acabar cruzando una.
9
+ */
10
+ exports.DESPACHO_DEL_MOTOR = 'DESPACHO_DEL_MOTOR';
11
+ exports.CORRIDA_DEL_MOTOR = 'CORRIDA_DEL_MOTOR';
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Las plantillas de payload de un servicio de trigger.
3
+ *
4
+ * ## Por qué es un contrato y no un import
5
+ *
6
+ * El registro son **23 ficheros y 5.800 líneas** de plantillas —una por
7
+ * servicio, y varias miran su config: `changeType` en Calendar, `eventTrigger`
8
+ * en Gmail, `enabledEvents` en Sheets—. Viven con el trigger, que es uno de los
9
+ * cinco nodos de origen que se quedan en el gateway.
10
+ *
11
+ * `start-node-sample.ts` las necesita para el paso 3 de «con qué payload
12
+ * arranca una corrida», y ese fichero viaja con el motor. Demasiado para
13
+ * mudarlo, y demasiado poco para copiarlo: de tener dos copias de una plantilla
14
+ * salió que un trigger de Google Calendar arrancara con
15
+ * `{ event: "new_email" }`.
16
+ *
17
+ * ⚠️ Y NO se escriben a mano en ningún lado: pasan por el MISMO formateador que
18
+ * la entrega real, así que no pueden desfasarse de lo que se despacha. Una copia
19
+ * sí se desfasa.
20
+ */
21
+ export type PlantillasDeOrigen = (service: string | null | undefined, serviceConfig: Record<string, unknown> | undefined) => Array<{
22
+ payload: Record<string, unknown>;
23
+ }>;
24
+ /** ⚠️ Cadena y no `Symbol`. */
25
+ export declare const PLANTILLAS_DE_ORIGEN = "PLANTILLAS_DE_ORIGEN";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PLANTILLAS_DE_ORIGEN = void 0;
4
+ /** ⚠️ Cadena y no `Symbol`. */
5
+ exports.PLANTILLAS_DE_ORIGEN = 'PLANTILLAS_DE_ORIGEN';