@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,60 @@
1
+ "use strict";
2
+ /**
3
+ * Lo que un nodo apunta en el registro. Una sola operación.
4
+ *
5
+ * ## Por qué
6
+ *
7
+ * Costura de la Fase 2. Después del #459 quedaban 16 ficheros de `nodes/`
8
+ * importando `TelemetryService`, más tres del motor en `common/` —que viaja
9
+ * con ellos—. Los 19 lo usan para **lo mismo**: `emit`.
10
+ *
11
+ * `TelemetryService` arrastra la colección de logs, su conexión de Mongo
12
+ * propia y el gateway de sockets que empuja la fila al panel en vivo. Nada de
13
+ * eso puede vivir en `hw-nodes`: el registro es del gateway, y lo que el nodo
14
+ * necesita es poder DECIR lo que ha pasado.
15
+ *
16
+ * ## Tres métodos, y medidos
17
+ *
18
+ * En `nodes/` el inventario dio **uno solo** —`emit`— en 15 de los 16
19
+ * ficheros. El que sobraba (`ai-nodes.controller`) no lo llamaba: se lo
20
+ * pasaba al probador, y para eso ya existe la bandera `conTelemetria` desde
21
+ * el #458.
22
+ *
23
+ * ⚠️ Pero el inventario iba apuntado sólo a `nodes/`, y el motor vive en
24
+ * `common/`, que viaja con ellos. Al compilar salieron dos métodos más:
25
+ * `hasRecentSuccess` y `emitAndWait`. Los dos son de la recuperación de
26
+ * caídas, no del registro: sin ellos un nodo caro se re-ejecuta. Lo cazó tsc,
27
+ * no yo — la lección de siempre, con el barrido mal apuntado.
28
+ *
29
+ * ⚠️ Y ahí apareció una regresión MÍA. El #459 le quitó a
30
+ * `code-nodes.controller` el parámetro `telemetry` y su `super()`, pero dejó
31
+ * en pie un `this.telemetry` en la ruta `:id/test` escrita a mano. Desde
32
+ * entonces valía `undefined`, así que un paso de Run Pipeline sobre un Code
33
+ * node **no anotaba nada** — justo el comportamiento que el #459 decía haber
34
+ * conservado. No lo vio tsc porque la clase base del factory está tipada como
35
+ * `=> any`: dentro de una subclase, `this.loquesea` compila.
36
+ *
37
+ * ## Los campos son los que se usan
38
+ *
39
+ * El esquema `TelemetryLog` tiene ~20 campos. Se contaron los que aparecen de
40
+ * verdad en las 67 llamadas de `nodes/` y las 53 de `common/`: son quince.
41
+ * Fuera quedan `timestamp` —lo pone el gateway si falta—, `correlationId` y
42
+ * los dos de voz, que nadie de este lado escribe.
43
+ *
44
+ * ## Cómo viaja
45
+ *
46
+ * Bien: sólo datos planos. `TelemetryLog` es una clase con decoradores pero
47
+ * sin métodos, así que no hay documento vivo que aplanar; aun así el contrato
48
+ * lo declara aparte para no arrastrar `@nestjs/mongoose` a `hw-nodes`.
49
+ *
50
+ * ⚠️ `emit` devuelve `void` y no espera: por dentro hace `create(...).catch()`.
51
+ * Eso es deliberado y hay que conservarlo cuando esto sea una llamada de red —
52
+ * un nodo no puede quedarse esperando a que se escriba una fila de log, y
53
+ * menos aún fallar porque no se pudo escribir.
54
+ */
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ exports.TELEMETRIA = void 0;
57
+ /**
58
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
59
+ */
60
+ exports.TELEMETRIA = 'TELEMETRIA';
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Lo que el AI Node apunta y consulta sobre sus llamadas al modelo.
3
+ *
4
+ * Costura de la Fase 2, del lote de las pequeñas. `LlmTracesClientService` es
5
+ * un CLIENTE HTTP contra `hw-llm-traces`, que ya es un servicio aparte — el
6
+ * coste de los logs no vive en esta api. Aun así el nodo no debe conocer al
7
+ * cliente: arrastra su configuración, su reintento y su autenticación.
8
+ *
9
+ * ## Cómo viaja
10
+ *
11
+ * ⚠️ `emitTrace` devuelve `Promise<void>` y su llamante NO la espera: apuntar
12
+ * una traza no puede retrasar una respuesta del modelo ni tumbarla. Eso hay
13
+ * que conservarlo.
14
+ *
15
+ * Las dos consultas devuelven `unknown` a propósito — es lo que devuelve el
16
+ * cliente real, que reenvía lo que conteste el servicio de trazas sin darle
17
+ * forma. Tipar aquí una forma que allí no se garantiza sería inventarla.
18
+ */
19
+ /** Lo que se apunta de una llamada al modelo. */
20
+ export interface TrazaDeLlm {
21
+ traceId?: string;
22
+ spanId?: string;
23
+ startTime: string | Date;
24
+ endTime?: string | Date;
25
+ provider: 'openai' | 'anthropic' | 'google' | 'ollama' | 'mistral' | 'cohere' | 'custom';
26
+ model: string;
27
+ operation?: 'chat' | 'completion' | 'embedding' | 'image' | 'audio';
28
+ inputTokens?: number;
29
+ outputTokens?: number;
30
+ cacheReadInputTokens?: number;
31
+ cacheCreationInputTokens?: number;
32
+ costUsd?: number;
33
+ status?: 'success' | 'error' | 'timeout';
34
+ error?: {
35
+ message?: string;
36
+ code?: string;
37
+ httpStatus?: number;
38
+ };
39
+ input?: {
40
+ messages?: unknown;
41
+ system?: unknown;
42
+ truncated?: boolean;
43
+ };
44
+ output?: {
45
+ content?: string;
46
+ toolCalls?: unknown[];
47
+ stopReason?: string;
48
+ truncated?: boolean;
49
+ };
50
+ metadata?: Record<string, unknown>;
51
+ aiNodeId?: string;
52
+ aiNodeName?: string;
53
+ eventId?: string;
54
+ workspaceId?: string;
55
+ invokedFrom?: string;
56
+ tags?: string[];
57
+ }
58
+ /** Los filtros con que la pantalla pide trazas. */
59
+ export interface FiltrosDeTrazas {
60
+ limit?: number;
61
+ offset?: number;
62
+ aiNodeId?: string;
63
+ status?: 'success' | 'error' | 'timeout';
64
+ model?: string;
65
+ provider?: string;
66
+ startAfter?: string;
67
+ startBefore?: string;
68
+ search?: string;
69
+ sortBy?: 'startTime' | 'costUsd' | 'latencyMs';
70
+ sortOrder?: 'asc' | 'desc';
71
+ }
72
+ export interface TrazasDeLlm {
73
+ queryTraces(orgId: string, params: FiltrosDeTrazas): Promise<unknown>;
74
+ getTrace(orgId: string, traceId: string): Promise<unknown>;
75
+ /** ⚠️ No se espera. Ver la cabecera. */
76
+ emitTrace(orgId: string, traza: TrazaDeLlm): Promise<void>;
77
+ }
78
+ /** ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2. */
79
+ export declare const TRAZAS_DE_LLM = "TRAZAS_DE_LLM";
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Lo que el AI Node apunta y consulta sobre sus llamadas al modelo.
4
+ *
5
+ * Costura de la Fase 2, del lote de las pequeñas. `LlmTracesClientService` es
6
+ * un CLIENTE HTTP contra `hw-llm-traces`, que ya es un servicio aparte — el
7
+ * coste de los logs no vive en esta api. Aun así el nodo no debe conocer al
8
+ * cliente: arrastra su configuración, su reintento y su autenticación.
9
+ *
10
+ * ## Cómo viaja
11
+ *
12
+ * ⚠️ `emitTrace` devuelve `Promise<void>` y su llamante NO la espera: apuntar
13
+ * una traza no puede retrasar una respuesta del modelo ni tumbarla. Eso hay
14
+ * que conservarlo.
15
+ *
16
+ * Las dos consultas devuelven `unknown` a propósito — es lo que devuelve el
17
+ * cliente real, que reenvía lo que conteste el servicio de trazas sin darle
18
+ * forma. Tipar aquí una forma que allí no se garantiza sería inventarla.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.TRAZAS_DE_LLM = void 0;
22
+ /** ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2. */
23
+ exports.TRAZAS_DE_LLM = 'TRAZAS_DE_LLM';
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Lo que un nodo necesita de un túnel. Dos cosas, y por dos caminos distintos.
3
+ *
4
+ * ## Por qué
5
+ *
6
+ * Costura de la Fase 2. `nodes/` importaba `tunnels/` así:
7
+ *
8
+ * 5 `TcpTunnelPool` el pool de reenviadores TCP
9
+ * 1 `TunnelsService` para comprobar que un túnel es de la organización
10
+ * 1 `tunnels.module` cableado
11
+ *
12
+ * ## ⚠️ Ésta NO es como las anteriores: el pool no puede mudarse
13
+ *
14
+ * Las once costuras anteriores acababan igual — el nodo pide por contrato y
15
+ * el día de la Fase 4 el contrato se convierte en una llamada HTTP. Aquí eso
16
+ * **no funciona**, y conviene decirlo antes de que alguien lo intente.
17
+ *
18
+ * `TcpTunnelPool.getOrCreate()` devuelve un reenviador que abre un **listener
19
+ * TCP en 127.0.0.1**, y lo que el nodo hace con él es apuntar ahí el driver de
20
+ * Mongo o de Postgres. Un `host:port` local sólo sirve dentro del proceso que
21
+ * lo abrió: pedirlo por red devolvería una dirección de otra máquina.
22
+ *
23
+ * Y el otro extremo tampoco se mueve: el pool se enchufa al servidor de
24
+ * sockets en el arranque —`webhook.gateway.ts` llama a `setGateway(this)`—
25
+ * porque los bytes del túnel viajan por la conexión que el cliente del
26
+ * usuario mantiene ABIERTA contra el gateway.
27
+ *
28
+ * O sea que el día de la mudanza hay dos salidas, y ninguna es «que el
29
+ * contrato hable HTTP»:
30
+ *
31
+ * a) el pool se va con los nodos, y `hw-nodes` mantiene su propio enlace de
32
+ * sockets con los clientes de túnel;
33
+ * b) los nodos de base de datos por túnel se quedan en el gateway.
34
+ *
35
+ * Lo que este contrato SÍ consigue hoy es que `nodes/` deje de importar la
36
+ * clase —con su reenviador, sus sockets y su barrido— y que la decisión de
37
+ * arriba se pueda tomar cambiando un registro, no cinco ficheros.
38
+ *
39
+ * ## Por qué un registro y no un token
40
+ *
41
+ * ⚠️ Dos de los cuatro llamantes del pool no tienen DI: uno es un método
42
+ * `static` (`ExternalMongoBackend.resolveCollection`) y otro una función
43
+ * suelta (`resolvePool` en el backend de Postgres). Un token de Nest no llega
44
+ * ahí.
45
+ *
46
+ * El registro de módulo es el patrón que ya usa `probador-de-nodos.ts` desde
47
+ * el #458, por el mismo motivo. Lo enchufa un provider con `onModuleInit`
48
+ * —ver `tunnels/monta-el-tunel-local.ts`— para que se pueda PROBAR que el
49
+ * registro ocurrió: un registro no lo garantiza el compilador.
50
+ *
51
+ * El otro contrato, `TunelesDeLaOrganizacion`, sí va por token: su único
52
+ * llamante es un servicio con constructor.
53
+ */
54
+ /** Una dirección a la que conectar un driver. Siempre en `127.0.0.1`. */
55
+ export interface DireccionLocal {
56
+ host: string;
57
+ port: number;
58
+ }
59
+ /**
60
+ * Un túnel, visto desde el nodo: «dame una dirección local que salga ahí».
61
+ *
62
+ * Los cuatro llamantes hacían exactamente los mismos dos pasos —pedir el
63
+ * reenviador al pool y sacarle `getLocalAddress()`—, así que el contrato es
64
+ * uno solo.
65
+ */
66
+ export interface TunelLocal {
67
+ /**
68
+ * ⚠️ Lanza si el túnel no está enchufado al gateway. Es lo que hace hoy
69
+ * `getOrCreate`, y hay que conservarlo: devolver una dirección que no
70
+ * escucha convertiría un error claro en un timeout del driver.
71
+ */
72
+ direccionLocalPara(tunnelId: string, host: string, port: number): Promise<DireccionLocal>;
73
+ }
74
+ /** Lo llama `tunnels/monta-el-tunel-local.ts` al arrancar. */
75
+ export declare function registrarTunelLocal(t: TunelLocal): void;
76
+ /** Para los tests, que montan el suyo. */
77
+ export declare function olvidarTunelLocal(): void;
78
+ export declare function hayTunelLocal(): boolean;
79
+ /**
80
+ * ⚠️ Lanza con un mensaje que dice QUÉ falta. Si nadie registró, el nodo no
81
+ * puede abrir el túnel, y un `undefined` silencioso acabaría en un error del
82
+ * driver a diez fotogramas de distancia de la causa.
83
+ */
84
+ export declare function obtenerTunelLocal(): TunelLocal;
85
+ /** Lo que el nodo pregunta sobre a quién pertenece un túnel. */
86
+ export interface TunelesDeLaOrganizacion {
87
+ /**
88
+ * ⚠️ Devuelve `unknown` y LANZA si el túnel no existe o no es de esa
89
+ * organización.
90
+ *
91
+ * `unknown` porque el servicio real devuelve el documento de Mongoose y su
92
+ * único llamante lo DESCARTA: sólo le importa si lanzó. Así el documento no
93
+ * cruza y el llamante no puede usarlo sin un cast.
94
+ *
95
+ * ⚠️ Y una nota para la Fase 4: ese llamante envuelve la llamada en un
96
+ * `catch` que lo convierte todo en «Tunnel not found». Hoy da igual —lo
97
+ * único que puede fallar es la consulta—, pero en cuanto esto sea una
98
+ * llamada de red, un corte de red se leerá como «el túnel no existe». Quien
99
+ * lo implemente por HTTP tiene que distinguir las dos cosas ahí.
100
+ */
101
+ asegurarQueEsDeLaOrganizacion(tunnelId: string, orgId: string): Promise<unknown>;
102
+ }
103
+ /**
104
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
105
+ */
106
+ export declare const TUNELES_DE_LA_ORGANIZACION = "TUNELES_DE_LA_ORGANIZACION";
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ /**
3
+ * Lo que un nodo necesita de un túnel. Dos cosas, y por dos caminos distintos.
4
+ *
5
+ * ## Por qué
6
+ *
7
+ * Costura de la Fase 2. `nodes/` importaba `tunnels/` así:
8
+ *
9
+ * 5 `TcpTunnelPool` el pool de reenviadores TCP
10
+ * 1 `TunnelsService` para comprobar que un túnel es de la organización
11
+ * 1 `tunnels.module` cableado
12
+ *
13
+ * ## ⚠️ Ésta NO es como las anteriores: el pool no puede mudarse
14
+ *
15
+ * Las once costuras anteriores acababan igual — el nodo pide por contrato y
16
+ * el día de la Fase 4 el contrato se convierte en una llamada HTTP. Aquí eso
17
+ * **no funciona**, y conviene decirlo antes de que alguien lo intente.
18
+ *
19
+ * `TcpTunnelPool.getOrCreate()` devuelve un reenviador que abre un **listener
20
+ * TCP en 127.0.0.1**, y lo que el nodo hace con él es apuntar ahí el driver de
21
+ * Mongo o de Postgres. Un `host:port` local sólo sirve dentro del proceso que
22
+ * lo abrió: pedirlo por red devolvería una dirección de otra máquina.
23
+ *
24
+ * Y el otro extremo tampoco se mueve: el pool se enchufa al servidor de
25
+ * sockets en el arranque —`webhook.gateway.ts` llama a `setGateway(this)`—
26
+ * porque los bytes del túnel viajan por la conexión que el cliente del
27
+ * usuario mantiene ABIERTA contra el gateway.
28
+ *
29
+ * O sea que el día de la mudanza hay dos salidas, y ninguna es «que el
30
+ * contrato hable HTTP»:
31
+ *
32
+ * a) el pool se va con los nodos, y `hw-nodes` mantiene su propio enlace de
33
+ * sockets con los clientes de túnel;
34
+ * b) los nodos de base de datos por túnel se quedan en el gateway.
35
+ *
36
+ * Lo que este contrato SÍ consigue hoy es que `nodes/` deje de importar la
37
+ * clase —con su reenviador, sus sockets y su barrido— y que la decisión de
38
+ * arriba se pueda tomar cambiando un registro, no cinco ficheros.
39
+ *
40
+ * ## Por qué un registro y no un token
41
+ *
42
+ * ⚠️ Dos de los cuatro llamantes del pool no tienen DI: uno es un método
43
+ * `static` (`ExternalMongoBackend.resolveCollection`) y otro una función
44
+ * suelta (`resolvePool` en el backend de Postgres). Un token de Nest no llega
45
+ * ahí.
46
+ *
47
+ * El registro de módulo es el patrón que ya usa `probador-de-nodos.ts` desde
48
+ * el #458, por el mismo motivo. Lo enchufa un provider con `onModuleInit`
49
+ * —ver `tunnels/monta-el-tunel-local.ts`— para que se pueda PROBAR que el
50
+ * registro ocurrió: un registro no lo garantiza el compilador.
51
+ *
52
+ * El otro contrato, `TunelesDeLaOrganizacion`, sí va por token: su único
53
+ * llamante es un servicio con constructor.
54
+ */
55
+ Object.defineProperty(exports, "__esModule", { value: true });
56
+ exports.TUNELES_DE_LA_ORGANIZACION = void 0;
57
+ exports.registrarTunelLocal = registrarTunelLocal;
58
+ exports.olvidarTunelLocal = olvidarTunelLocal;
59
+ exports.hayTunelLocal = hayTunelLocal;
60
+ exports.obtenerTunelLocal = obtenerTunelLocal;
61
+ let tunelLocal = null;
62
+ /** Lo llama `tunnels/monta-el-tunel-local.ts` al arrancar. */
63
+ function registrarTunelLocal(t) {
64
+ tunelLocal = t;
65
+ }
66
+ /** Para los tests, que montan el suyo. */
67
+ function olvidarTunelLocal() {
68
+ tunelLocal = null;
69
+ }
70
+ function hayTunelLocal() {
71
+ return tunelLocal !== null;
72
+ }
73
+ /**
74
+ * ⚠️ Lanza con un mensaje que dice QUÉ falta. Si nadie registró, el nodo no
75
+ * puede abrir el túnel, y un `undefined` silencioso acabaría en un error del
76
+ * driver a diez fotogramas de distancia de la causa.
77
+ */
78
+ function obtenerTunelLocal() {
79
+ if (!tunelLocal) {
80
+ throw new Error('Nadie registró el túnel local — `MontaElTunelLocal` tiene que estar en los providers de `TunnelsModule`');
81
+ }
82
+ return tunelLocal;
83
+ }
84
+ /**
85
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
86
+ */
87
+ exports.TUNELES_DE_LA_ORGANIZACION = 'TUNELES_DE_LA_ORGANIZACION';
@@ -0,0 +1,39 @@
1
+ /**
2
+ * La pregunta que hace el guardia de workspace: ¿puede este usuario tocar
3
+ * este recurso?
4
+ *
5
+ * Costura de la Fase 2, del lote de las pequeñas. El guardia resolvía el
6
+ * workspace del recurso con la CONEXIÓN de Mongoose —`connection.model(...)`—
7
+ * y luego comprobaba el acceso con ella otra vez. Eso es la base de datos del
8
+ * gateway, y no puede viajar.
9
+ *
10
+ * Mismo reparto que el guardia de credenciales del #457: el guardia se muda,
11
+ * la consulta se queda y se pregunta por contrato.
12
+ *
13
+ * ## ⚠️ Lo que hay que conservar
14
+ *
15
+ * - **Si el recurso NO existe, se deja pasar.** El manejador contestará 404
16
+ * como hasta ahora; un 403 aquí diría «existe pero no es tuyo» sobre algo
17
+ * que no existe, que es filtrar información.
18
+ * - **Si el modelo no está registrado, LANZA.** Un nombre mal escrito tiene
19
+ * que reventar la ruta la primera vez, no dejar pasar todo en silencio.
20
+ * - **Deniega lanzando**, no devolviendo `false`. Es lo que hace hoy
21
+ * `asegurarAccesoAlWorkspace`, y el guardia cuenta con ello.
22
+ */
23
+ export interface AccesoAlRecurso {
24
+ /**
25
+ * Lanza si el usuario no puede con ese recurso. Vuelve sin más si puede —
26
+ * o si el recurso no existe. Ver la cabecera.
27
+ */
28
+ asegurarAcceso(params: {
29
+ /** Nombre del MODELO de Mongoose, no de la colección. */
30
+ modelo: string;
31
+ /** Campo contra el que se compara el id. Casi siempre `_id`. */
32
+ campo: string;
33
+ id: string;
34
+ orgId: string;
35
+ userId: string;
36
+ }): Promise<void>;
37
+ }
38
+ /** ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2. */
39
+ export declare const ACCESO_AL_RECURSO = "ACCESO_AL_RECURSO";
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ACCESO_AL_RECURSO = void 0;
4
+ /** ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2. */
5
+ exports.ACCESO_AL_RECURSO = 'ACCESO_AL_RECURSO';
@@ -0,0 +1,40 @@
1
+ /**
2
+ * En qué zona horaria vive un usuario. Una pregunta, un campo.
3
+ *
4
+ * ## Por qué
5
+ *
6
+ * Último trozo de la costura `nodes/` → `auth/`. `ScheduledWorkflowsService`
7
+ * inyectaba el modelo de `User` para leer **un campo**: la zona horaria con la
8
+ * que programar un cron cuando el DTO no la trae.
9
+ *
10
+ * Un servicio de nodo consultando la colección de usuarios es justo lo que no
11
+ * puede viajar a `hw-nodes`: allí no hay colección de usuarios, y no debe
12
+ * haberla — la identidad vive en el gateway.
13
+ *
14
+ * ## Lo que se conserva
15
+ *
16
+ * ⚠️ La caída a `'UTC'`, y en los DOS casos que ya tenía: si el usuario no
17
+ * existe, y si la consulta falla. Eso no es un detalle: sin zona horaria un
18
+ * cron no se puede programar, así que el original prefería una por defecto a
19
+ * reventar la creación del nodo. Quien implemente esto por HTTP tiene que
20
+ * seguir cayendo a `'UTC'` cuando el gateway no conteste — está escrito en el
21
+ * contrato para que no se pierda por el camino.
22
+ *
23
+ * ## Y esto viaja
24
+ *
25
+ * Una cadena. Como los topes del plan y a diferencia de la costura del motor,
26
+ * aquí no hay nada que aplanar.
27
+ */
28
+ export interface ZonaHorariaDelUsuario {
29
+ /**
30
+ * ⚠️ Nunca lanza y nunca devuelve vacío: si no se sabe, `'UTC'`.
31
+ *
32
+ * Devolver `null` obligaría a cada llamante a decidir el respaldo, y ése es
33
+ * el tipo de decisión que se toma distinta en cada sitio.
34
+ */
35
+ zonaDe(userId: string): Promise<string>;
36
+ }
37
+ /**
38
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
39
+ */
40
+ export declare const ZONA_HORARIA_DEL_USUARIO = "ZONA_HORARIA_DEL_USUARIO";
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ZONA_HORARIA_DEL_USUARIO = void 0;
4
+ /**
5
+ * ⚠️ Cadena y no `Symbol`, igual que el resto de tokens de la Fase 2.
6
+ */
7
+ exports.ZONA_HORARIA_DEL_USUARIO = 'ZONA_HORARIA_DEL_USUARIO';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostwebhook/platform-contracts",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Contratos compartidos entre los servicios de HostWebhook: addons del plan, identidad interna, y las formas que cruzan una frontera de red",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,7 +8,7 @@
8
8
  "dist"
9
9
  ],
10
10
  "scripts": {
11
- "build": "tsc",
11
+ "build": "npm --prefix ../node-types run build && tsc",
12
12
  "test": "vitest run",
13
13
  "prepublishOnly": "npm run build"
14
14
  },
@@ -20,6 +20,12 @@
20
20
  "license": "MIT",
21
21
  "devDependencies": {
22
22
  "typescript": "^5.0.0",
23
- "vitest": "^3.0.0"
23
+ "vitest": "^3.0.0",
24
+ "@nestjs/common": "^11.0.0",
25
+ "@hostwebhook/node-types": "*"
26
+ },
27
+ "peerDependencies": {
28
+ "@nestjs/common": ">=11.0.0 <12",
29
+ "@hostwebhook/node-types": ">=1.67.0 <2"
24
30
  }
25
31
  }