@fiado/type-kit 3.293.0 → 3.295.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.
- package/_test_/unit/platformRbac/enums/__snapshots__/permissionBits.test.ts.snap +6 -1
- package/bin/emailVerification/dtos/internal/EmailStartByDirectoryRequest.d.ts +10 -0
- package/bin/emailVerification/dtos/internal/EmailStartByDirectoryRequest.js +37 -0
- package/bin/emailVerification/dtos/internal/EmailStartByDirectoryResponse.d.ts +9 -0
- package/bin/emailVerification/dtos/internal/EmailStartByDirectoryResponse.js +32 -0
- package/bin/emailVerification/index.d.ts +2 -0
- package/bin/emailVerification/index.js +2 -0
- package/bin/platformRbac/dtos/CreateIntegrationRequest.d.ts +21 -0
- package/bin/platformRbac/dtos/CreateIntegrationRequest.js +57 -0
- package/bin/platformRbac/dtos/IntegrationKeyResponse.d.ts +39 -0
- package/bin/platformRbac/dtos/IntegrationKeyResponse.js +2 -0
- package/bin/platformRbac/dtos/IntegrationResponse.d.ts +25 -0
- package/bin/platformRbac/dtos/IntegrationResponse.js +2 -0
- package/bin/platformRbac/dtos/IntegrationWhoamiResponse.d.ts +21 -0
- package/bin/platformRbac/dtos/IntegrationWhoamiResponse.js +2 -0
- package/bin/platformRbac/dtos/UpdateIntegrationRequest.d.ts +18 -0
- package/bin/platformRbac/dtos/UpdateIntegrationRequest.js +51 -0
- package/bin/platformRbac/enums/Permission.d.ts +6 -1
- package/bin/platformRbac/enums/Permission.js +22 -0
- package/bin/platformRbac/index.d.ts +5 -0
- package/bin/platformRbac/index.js +4 -0
- package/package.json +1 -1
- package/src/emailVerification/dtos/internal/EmailStartByDirectoryRequest.ts +22 -0
- package/src/emailVerification/dtos/internal/EmailStartByDirectoryResponse.ts +16 -0
- package/src/emailVerification/index.ts +2 -0
- package/src/platformRbac/dtos/CreateIntegrationRequest.ts +24 -0
- package/src/platformRbac/dtos/IntegrationKeyResponse.ts +41 -0
- package/src/platformRbac/dtos/IntegrationResponse.ts +26 -0
- package/src/platformRbac/dtos/IntegrationWhoamiResponse.ts +21 -0
- package/src/platformRbac/dtos/UpdateIntegrationRequest.ts +21 -0
- package/src/platformRbac/enums/Permission.ts +24 -0
- package/src/platformRbac/index.ts +12 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
|
2
2
|
|
|
3
|
-
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `
|
|
3
|
+
exports[`PERMISSION_BIT_ORDER PERMS_VERSION es número estable 1`] = `3833769424`;
|
|
4
4
|
|
|
5
5
|
exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe ante cualquier reorden/inserción) 1`] = `
|
|
6
6
|
[
|
|
@@ -90,5 +90,10 @@ exports[`PERMISSION_BIT_ORDER append-only: snapshot del ORDEN COMPLETO (rompe an
|
|
|
90
90
|
"level3.role.assign",
|
|
91
91
|
"level3.role.revoke",
|
|
92
92
|
"level3.audit.view",
|
|
93
|
+
"platform.integration.view",
|
|
94
|
+
"platform.integration.manage",
|
|
95
|
+
"platform.integration.key.issue",
|
|
96
|
+
"platform.integration.key.revoke",
|
|
97
|
+
"tenant.integration.diagnostic",
|
|
93
98
|
]
|
|
94
99
|
`;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request interno (api-invoker) para registrar un email y disparar su verificación.
|
|
3
|
+
* `directoryId` es @IsString (cognitoSub UUID v7 — no usar @IsUUID).
|
|
4
|
+
*/
|
|
5
|
+
export declare class EmailStartByDirectoryRequest {
|
|
6
|
+
directoryId: string;
|
|
7
|
+
email: string;
|
|
8
|
+
/** Nombre para el saludo del correo. Default "Cliente". */
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailStartByDirectoryRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Request interno (api-invoker) para registrar un email y disparar su verificación.
|
|
17
|
+
* `directoryId` es @IsString (cognitoSub UUID v7 — no usar @IsUUID).
|
|
18
|
+
*/
|
|
19
|
+
class EmailStartByDirectoryRequest {
|
|
20
|
+
}
|
|
21
|
+
exports.EmailStartByDirectoryRequest = EmailStartByDirectoryRequest;
|
|
22
|
+
__decorate([
|
|
23
|
+
(0, class_transformer_1.Expose)(),
|
|
24
|
+
(0, class_validator_1.IsString)(),
|
|
25
|
+
__metadata("design:type", String)
|
|
26
|
+
], EmailStartByDirectoryRequest.prototype, "directoryId", void 0);
|
|
27
|
+
__decorate([
|
|
28
|
+
(0, class_transformer_1.Expose)(),
|
|
29
|
+
(0, class_validator_1.IsEmail)(),
|
|
30
|
+
__metadata("design:type", String)
|
|
31
|
+
], EmailStartByDirectoryRequest.prototype, "email", void 0);
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_transformer_1.Expose)(),
|
|
34
|
+
(0, class_validator_1.IsOptional)(),
|
|
35
|
+
(0, class_validator_1.IsString)(),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], EmailStartByDirectoryRequest.prototype, "name", void 0);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EmailVerificationStatusEnum } from '../../enums/EmailVerificationStatusEnum';
|
|
2
|
+
/**
|
|
3
|
+
* Response interno del alta + disparo de verificación de un email por directorio.
|
|
4
|
+
*/
|
|
5
|
+
export declare class EmailStartByDirectoryResponse {
|
|
6
|
+
email: string;
|
|
7
|
+
verificationId: string;
|
|
8
|
+
status: EmailVerificationStatusEnum;
|
|
9
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.EmailStartByDirectoryResponse = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const EmailVerificationStatusEnum_1 = require("../../enums/EmailVerificationStatusEnum");
|
|
15
|
+
/**
|
|
16
|
+
* Response interno del alta + disparo de verificación de un email por directorio.
|
|
17
|
+
*/
|
|
18
|
+
class EmailStartByDirectoryResponse {
|
|
19
|
+
}
|
|
20
|
+
exports.EmailStartByDirectoryResponse = EmailStartByDirectoryResponse;
|
|
21
|
+
__decorate([
|
|
22
|
+
(0, class_transformer_1.Expose)(),
|
|
23
|
+
__metadata("design:type", String)
|
|
24
|
+
], EmailStartByDirectoryResponse.prototype, "email", void 0);
|
|
25
|
+
__decorate([
|
|
26
|
+
(0, class_transformer_1.Expose)(),
|
|
27
|
+
__metadata("design:type", String)
|
|
28
|
+
], EmailStartByDirectoryResponse.prototype, "verificationId", void 0);
|
|
29
|
+
__decorate([
|
|
30
|
+
(0, class_transformer_1.Expose)(),
|
|
31
|
+
__metadata("design:type", String)
|
|
32
|
+
], EmailStartByDirectoryResponse.prototype, "status", void 0);
|
|
@@ -17,3 +17,5 @@ export * from './dtos/internal/PrimaryEmailByDirectoryRequest';
|
|
|
17
17
|
export * from './dtos/internal/PrimaryEmailResponse';
|
|
18
18
|
export * from './dtos/internal/EmailsByDirectoryRequest';
|
|
19
19
|
export * from './dtos/internal/EmailsByDirectoryResponse';
|
|
20
|
+
export * from './dtos/internal/EmailStartByDirectoryRequest';
|
|
21
|
+
export * from './dtos/internal/EmailStartByDirectoryResponse';
|
|
@@ -33,3 +33,5 @@ __exportStar(require("./dtos/internal/PrimaryEmailByDirectoryRequest"), exports)
|
|
|
33
33
|
__exportStar(require("./dtos/internal/PrimaryEmailResponse"), exports);
|
|
34
34
|
__exportStar(require("./dtos/internal/EmailsByDirectoryRequest"), exports);
|
|
35
35
|
__exportStar(require("./dtos/internal/EmailsByDirectoryResponse"), exports);
|
|
36
|
+
__exportStar(require("./dtos/internal/EmailStartByDirectoryRequest"), exports);
|
|
37
|
+
__exportStar(require("./dtos/internal/EmailStartByDirectoryResponse"), exports);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Body del POST /platform/tenants/{tenantId}/integrations. `tenantId` viaja en el path.
|
|
3
|
+
*
|
|
4
|
+
* Da de alta una integración M2M con un socio externo (DEC-RBAC-120/121). Los datos son del tenant
|
|
5
|
+
* pero **solo un usuario de plataforma** puede crearla.
|
|
6
|
+
*
|
|
7
|
+
* `roleId` es un rol del silo del tenant, elegido de los que ya existen — no se siembra uno
|
|
8
|
+
* especial. Está sujeto a las guardas anti-escalada: no puede contener permisos de administración
|
|
9
|
+
* de integraciones ni calcular scope PLATFORM (DEC-RBAC-122/126).
|
|
10
|
+
*
|
|
11
|
+
* `ipAllowlist` es OPCIONAL y su semántica es permisiva (spec §5): ausente, vacía o `['*']` ⇒ sin
|
|
12
|
+
* restricción de IP. Que se pueda apagar es deliberado; que se apague en silencio, no — por eso la
|
|
13
|
+
* pantalla marca las integraciones sin restricción.
|
|
14
|
+
*/
|
|
15
|
+
export declare class CreateIntegrationRequest {
|
|
16
|
+
displayName: string;
|
|
17
|
+
roleId: string;
|
|
18
|
+
ipAllowlist?: string[];
|
|
19
|
+
/** cognitoSub del operador real (audit + grantedBy del assignment). */
|
|
20
|
+
createdBy: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CreateIntegrationRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Body del POST /platform/tenants/{tenantId}/integrations. `tenantId` viaja en el path.
|
|
17
|
+
*
|
|
18
|
+
* Da de alta una integración M2M con un socio externo (DEC-RBAC-120/121). Los datos son del tenant
|
|
19
|
+
* pero **solo un usuario de plataforma** puede crearla.
|
|
20
|
+
*
|
|
21
|
+
* `roleId` es un rol del silo del tenant, elegido de los que ya existen — no se siembra uno
|
|
22
|
+
* especial. Está sujeto a las guardas anti-escalada: no puede contener permisos de administración
|
|
23
|
+
* de integraciones ni calcular scope PLATFORM (DEC-RBAC-122/126).
|
|
24
|
+
*
|
|
25
|
+
* `ipAllowlist` es OPCIONAL y su semántica es permisiva (spec §5): ausente, vacía o `['*']` ⇒ sin
|
|
26
|
+
* restricción de IP. Que se pueda apagar es deliberado; que se apague en silencio, no — por eso la
|
|
27
|
+
* pantalla marca las integraciones sin restricción.
|
|
28
|
+
*/
|
|
29
|
+
class CreateIntegrationRequest {
|
|
30
|
+
}
|
|
31
|
+
exports.CreateIntegrationRequest = CreateIntegrationRequest;
|
|
32
|
+
__decorate([
|
|
33
|
+
(0, class_transformer_1.Expose)(),
|
|
34
|
+
(0, class_validator_1.IsString)(),
|
|
35
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], CreateIntegrationRequest.prototype, "displayName", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, class_transformer_1.Expose)(),
|
|
40
|
+
(0, class_validator_1.IsString)(),
|
|
41
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
42
|
+
__metadata("design:type", String)
|
|
43
|
+
], CreateIntegrationRequest.prototype, "roleId", void 0);
|
|
44
|
+
__decorate([
|
|
45
|
+
(0, class_transformer_1.Expose)(),
|
|
46
|
+
(0, class_validator_1.IsOptional)(),
|
|
47
|
+
(0, class_validator_1.IsArray)(),
|
|
48
|
+
(0, class_validator_1.ArrayNotEmpty)(),
|
|
49
|
+
(0, class_validator_1.IsString)({ each: true }),
|
|
50
|
+
__metadata("design:type", Array)
|
|
51
|
+
], CreateIntegrationRequest.prototype, "ipAllowlist", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
(0, class_transformer_1.Expose)(),
|
|
54
|
+
(0, class_validator_1.IsString)(),
|
|
55
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
56
|
+
__metadata("design:type", String)
|
|
57
|
+
], CreateIntegrationRequest.prototype, "createdBy", void 0);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estado de una llave. NO existe `ROTATING`: rotar es emitir una segunda llave y revocar la vieja,
|
|
3
|
+
* con las dos activas mientras dura la migración del socio.
|
|
4
|
+
*/
|
|
5
|
+
export type IntegrationKeyStatusValue = 'ACTIVE' | 'REVOKED';
|
|
6
|
+
/**
|
|
7
|
+
* Una llave, tal como la devuelve el listado.
|
|
8
|
+
*
|
|
9
|
+
* 🔴 **NUNCA lleva el secreto ni el `secretHash`.** El secreto en claro se devuelve exactamente una
|
|
10
|
+
* vez, en la respuesta del POST que lo emite (`IssueIntegrationKeyResponse`), y no existe ningún
|
|
11
|
+
* endpoint que lo lea de vuelta.
|
|
12
|
+
*
|
|
13
|
+
* `lastUsedAt` y `lastUsedIp` los escribe el authorizer W5, con throttle: sirven para detectar una
|
|
14
|
+
* integración que dejó de llamar, que es uno de los dos incidentes clásicos de un canal M2M.
|
|
15
|
+
*/
|
|
16
|
+
export interface IntegrationKeyResponse {
|
|
17
|
+
keyId: string;
|
|
18
|
+
integrationId: string;
|
|
19
|
+
status: IntegrationKeyStatusValue;
|
|
20
|
+
/** epoch ms. Ausente = no vence. */
|
|
21
|
+
expiresAt?: number;
|
|
22
|
+
lastUsedAt?: number;
|
|
23
|
+
lastUsedIp?: string;
|
|
24
|
+
createdAt: number;
|
|
25
|
+
createdBy?: string;
|
|
26
|
+
revokedAt?: number;
|
|
27
|
+
revokedBy?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Respuesta del POST que emite una llave. **El único lugar de todo el sistema donde el secreto
|
|
31
|
+
* viaja en claro.**
|
|
32
|
+
*
|
|
33
|
+
* Quien lo consuma tiene que mostrarlo una sola vez y no persistirlo: no hay forma de recuperarlo
|
|
34
|
+
* después, porque en base solo queda su hash. Si se pierde, se emite otra llave.
|
|
35
|
+
*/
|
|
36
|
+
export interface IssueIntegrationKeyResponse extends IntegrationKeyResponse {
|
|
37
|
+
/** `fdo_sk.<keyId>.<secreto>` — se muestra UNA vez y no se vuelve a poder leer. */
|
|
38
|
+
token: string;
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Estado de una integración. Suspender corta TODAS sus llaves de una. */
|
|
2
|
+
export type IntegrationStatusValue = 'ACTIVE' | 'SUSPENDED';
|
|
3
|
+
/**
|
|
4
|
+
* Una integración, tal como la devuelven el GET de detalle y el listado.
|
|
5
|
+
*
|
|
6
|
+
* NO lleva nada del secreto de sus llaves — ni el valor ni el hash. Para eso está
|
|
7
|
+
* `IntegrationKeyResponse`, que tampoco los lleva.
|
|
8
|
+
*/
|
|
9
|
+
export interface IntegrationResponse {
|
|
10
|
+
integrationId: string;
|
|
11
|
+
tenantId: string;
|
|
12
|
+
displayName: string;
|
|
13
|
+
status: IntegrationStatusValue;
|
|
14
|
+
/** Rol del silo que porta esta integración. */
|
|
15
|
+
roleId: string;
|
|
16
|
+
/**
|
|
17
|
+
* CIDRs permitidos. Vacío o `['*']` ⇒ **sin restricción de IP** (spec §5).
|
|
18
|
+
* El front lo marca visiblemente en la lista: la protección se puede apagar, pero no en silencio.
|
|
19
|
+
*/
|
|
20
|
+
ipAllowlist: string[];
|
|
21
|
+
createdAt: number;
|
|
22
|
+
updatedAt: number;
|
|
23
|
+
createdBy?: string;
|
|
24
|
+
updatedBy?: string;
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Respuesta del endpoint de diagnóstico del authorizer W5.
|
|
3
|
+
*
|
|
4
|
+
* Devuelve **el principal ya resuelto**, no un "ok". Eso es lo que lo hace útil como prueba de la
|
|
5
|
+
* cadena completa: no verifica que el request pase, sino que haya resuelto como quien debía —
|
|
6
|
+
* con el tenant correcto y con los permisos que su rol otorga.
|
|
7
|
+
*
|
|
8
|
+
* 🔴 Endpoint TEMPORAL, solo dev: expone la lista de permisos del principal. Se saca antes de
|
|
9
|
+
* producción (el permiso `tenant.integration.diagnostic` en cambio se queda, marcado deprecado:
|
|
10
|
+
* quitarlo del enum rompería la cobertura bidireccional del catálogo y dejaría
|
|
11
|
+
* `UnknownPermissionError` en cualquier rol ya sembrado con él).
|
|
12
|
+
*/
|
|
13
|
+
export interface IntegrationWhoamiResponse {
|
|
14
|
+
principalType: 'INTEGRATION';
|
|
15
|
+
/** Con prefijo `INT#`. */
|
|
16
|
+
principalId: string;
|
|
17
|
+
integrationId: string;
|
|
18
|
+
tenantId: string;
|
|
19
|
+
/** Los permisos que resolvió el RBAC para este principal — el punto de la prueba. */
|
|
20
|
+
permissions: string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Body del PUT /platform/tenants/{tenantId}/integrations/{integrationId}.
|
|
3
|
+
*
|
|
4
|
+
* ⚠️ **Semántica de MERGE, no de reemplazo**: solo se actualiza lo que venga. Un campo ausente se
|
|
5
|
+
* deja como está, NO se borra.
|
|
6
|
+
*
|
|
7
|
+
* Es PUT y no PATCH porque `PATCH` no existe en este stack — el enum `HttpMethod` del
|
|
8
|
+
* `@fiado/gateway-adapter` tiene GET/POST/PUT/DELETE, y el CORS y los `GatewayResponses` tampoco lo
|
|
9
|
+
* listan. Mismo precedente que `backofficeUpdateTenantUserField`.
|
|
10
|
+
*
|
|
11
|
+
* El merge no es cosmético: con reemplazo total, un body que omitiera `ipAllowlist` la borraría, y
|
|
12
|
+
* eso apagaría el filtro por IP de la integración sin que nadie lo pidiera.
|
|
13
|
+
*/
|
|
14
|
+
export declare class UpdateIntegrationRequest {
|
|
15
|
+
displayName?: string;
|
|
16
|
+
ipAllowlist?: string[];
|
|
17
|
+
updatedBy: string;
|
|
18
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.UpdateIntegrationRequest = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
/**
|
|
16
|
+
* Body del PUT /platform/tenants/{tenantId}/integrations/{integrationId}.
|
|
17
|
+
*
|
|
18
|
+
* ⚠️ **Semántica de MERGE, no de reemplazo**: solo se actualiza lo que venga. Un campo ausente se
|
|
19
|
+
* deja como está, NO se borra.
|
|
20
|
+
*
|
|
21
|
+
* Es PUT y no PATCH porque `PATCH` no existe en este stack — el enum `HttpMethod` del
|
|
22
|
+
* `@fiado/gateway-adapter` tiene GET/POST/PUT/DELETE, y el CORS y los `GatewayResponses` tampoco lo
|
|
23
|
+
* listan. Mismo precedente que `backofficeUpdateTenantUserField`.
|
|
24
|
+
*
|
|
25
|
+
* El merge no es cosmético: con reemplazo total, un body que omitiera `ipAllowlist` la borraría, y
|
|
26
|
+
* eso apagaría el filtro por IP de la integración sin que nadie lo pidiera.
|
|
27
|
+
*/
|
|
28
|
+
class UpdateIntegrationRequest {
|
|
29
|
+
}
|
|
30
|
+
exports.UpdateIntegrationRequest = UpdateIntegrationRequest;
|
|
31
|
+
__decorate([
|
|
32
|
+
(0, class_transformer_1.Expose)(),
|
|
33
|
+
(0, class_validator_1.IsOptional)(),
|
|
34
|
+
(0, class_validator_1.IsString)(),
|
|
35
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
36
|
+
__metadata("design:type", String)
|
|
37
|
+
], UpdateIntegrationRequest.prototype, "displayName", void 0);
|
|
38
|
+
__decorate([
|
|
39
|
+
(0, class_transformer_1.Expose)(),
|
|
40
|
+
(0, class_validator_1.IsOptional)(),
|
|
41
|
+
(0, class_validator_1.IsArray)(),
|
|
42
|
+
(0, class_validator_1.ArrayNotEmpty)(),
|
|
43
|
+
(0, class_validator_1.IsString)({ each: true }),
|
|
44
|
+
__metadata("design:type", Array)
|
|
45
|
+
], UpdateIntegrationRequest.prototype, "ipAllowlist", void 0);
|
|
46
|
+
__decorate([
|
|
47
|
+
(0, class_transformer_1.Expose)(),
|
|
48
|
+
(0, class_validator_1.IsString)(),
|
|
49
|
+
(0, class_validator_1.IsNotEmpty)(),
|
|
50
|
+
__metadata("design:type", String)
|
|
51
|
+
], UpdateIntegrationRequest.prototype, "updatedBy", void 0);
|
|
@@ -114,7 +114,12 @@ export declare enum Permission {
|
|
|
114
114
|
LEVEL3_ROLE_DELETE = "level3.role.delete",
|
|
115
115
|
LEVEL3_ROLE_ASSIGN = "level3.role.assign",
|
|
116
116
|
LEVEL3_ROLE_REVOKE = "level3.role.revoke",
|
|
117
|
-
LEVEL3_AUDIT_VIEW = "level3.audit.view"
|
|
117
|
+
LEVEL3_AUDIT_VIEW = "level3.audit.view",
|
|
118
|
+
PLATFORM_INTEGRATION_VIEW = "platform.integration.view",
|
|
119
|
+
PLATFORM_INTEGRATION_MANAGE = "platform.integration.manage",
|
|
120
|
+
PLATFORM_INTEGRATION_KEY_ISSUE = "platform.integration.key.issue",
|
|
121
|
+
PLATFORM_INTEGRATION_KEY_REVOKE = "platform.integration.key.revoke",
|
|
122
|
+
TENANT_INTEGRATION_DIAGNOSTIC = "tenant.integration.diagnostic"
|
|
118
123
|
}
|
|
119
124
|
/**
|
|
120
125
|
* Orden CANÓNICO y APPEND-ONLY de los permisos para el bitset del token.
|
|
@@ -149,6 +149,21 @@ var Permission;
|
|
|
149
149
|
Permission["LEVEL3_ROLE_ASSIGN"] = "level3.role.assign";
|
|
150
150
|
Permission["LEVEL3_ROLE_REVOKE"] = "level3.role.revoke";
|
|
151
151
|
Permission["LEVEL3_AUDIT_VIEW"] = "level3.audit.view";
|
|
152
|
+
// Append-only 2026-08-10 (DEC-RBAC-120/121/126): integraciones M2M con socios externos.
|
|
153
|
+
// Los cuatro de ADMINISTRACIÓN son scope PLATFORM: los datos de la integración son del tenant,
|
|
154
|
+
// pero solo un usuario de plataforma la crea, rota o revoca. Son además el set exacto que la
|
|
155
|
+
// guarda 1 prohíbe asignarle a un principal `INT#` — una integración jamás puede administrarse
|
|
156
|
+
// a sí misma.
|
|
157
|
+
Permission["PLATFORM_INTEGRATION_VIEW"] = "platform.integration.view";
|
|
158
|
+
Permission["PLATFORM_INTEGRATION_MANAGE"] = "platform.integration.manage";
|
|
159
|
+
Permission["PLATFORM_INTEGRATION_KEY_ISSUE"] = "platform.integration.key.issue";
|
|
160
|
+
Permission["PLATFORM_INTEGRATION_KEY_REVOKE"] = "platform.integration.key.revoke";
|
|
161
|
+
// DEC-RBAC-126: el endpoint de diagnóstico del authorizer W5 lo llama la INTEGRACIÓN, no un
|
|
162
|
+
// humano — y una integración NUNCA puede portar permisos de scope PLATFORM (computeRoleScope
|
|
163
|
+
// toma el MAX de los scopes del rol, así que uno solo lo volvería PLATFORM con scopeRef '*').
|
|
164
|
+
// Por eso este es TENANT-scoped. Y por eso NO entra en el set de la guarda 1: no administra
|
|
165
|
+
// nada, solo devuelve quién sos.
|
|
166
|
+
Permission["TENANT_INTEGRATION_DIAGNOSTIC"] = "tenant.integration.diagnostic";
|
|
152
167
|
})(Permission || (exports.Permission = Permission = {}));
|
|
153
168
|
/**
|
|
154
169
|
* Orden CANÓNICO y APPEND-ONLY de los permisos para el bitset del token.
|
|
@@ -261,6 +276,13 @@ exports.PERMISSION_BIT_ORDER = [
|
|
|
261
276
|
Permission.LEVEL3_ROLE_ASSIGN,
|
|
262
277
|
Permission.LEVEL3_ROLE_REVOKE,
|
|
263
278
|
Permission.LEVEL3_AUDIT_VIEW,
|
|
279
|
+
// Append-only 2026-08-10 (DEC-RBAC-120/126): integraciones M2M. Van AL FINAL y en este orden,
|
|
280
|
+
// nunca intercalados: reordenar desalinearía los bits de los tokens ya emitidos.
|
|
281
|
+
Permission.PLATFORM_INTEGRATION_VIEW,
|
|
282
|
+
Permission.PLATFORM_INTEGRATION_MANAGE,
|
|
283
|
+
Permission.PLATFORM_INTEGRATION_KEY_ISSUE,
|
|
284
|
+
Permission.PLATFORM_INTEGRATION_KEY_REVOKE,
|
|
285
|
+
Permission.TENANT_INTEGRATION_DIAGNOSTIC,
|
|
264
286
|
];
|
|
265
287
|
function djb2(input) {
|
|
266
288
|
let h = 5381;
|
|
@@ -55,3 +55,8 @@ export * from './dtos/CreateLevelEntityRequest';
|
|
|
55
55
|
export type { CreateLevelEntityResponse } from './dtos/CreateLevelEntityResponse';
|
|
56
56
|
export * from './dtos/CreateTenantUserRequest';
|
|
57
57
|
export type { CreateTenantUserResponse } from './dtos/CreateTenantUserResponse';
|
|
58
|
+
export * from './dtos/CreateIntegrationRequest';
|
|
59
|
+
export * from './dtos/UpdateIntegrationRequest';
|
|
60
|
+
export type { IntegrationResponse, IntegrationStatusValue } from './dtos/IntegrationResponse';
|
|
61
|
+
export type { IntegrationKeyResponse, IntegrationKeyStatusValue, IssueIntegrationKeyResponse, } from './dtos/IntegrationKeyResponse';
|
|
62
|
+
export type { IntegrationWhoamiResponse } from './dtos/IntegrationWhoamiResponse';
|
|
@@ -111,3 +111,7 @@ __exportStar(require("./dtos/SelfRegisterCompleteRequest"), exports);
|
|
|
111
111
|
// Response son interfaces plain → type-only. Consumidos por retail-org vía api-invoker (Publisher).
|
|
112
112
|
__exportStar(require("./dtos/CreateLevelEntityRequest"), exports);
|
|
113
113
|
__exportStar(require("./dtos/CreateTenantUserRequest"), exports);
|
|
114
|
+
// DEC-RBAC-120/121/126: integraciones M2M con socios externos (API keys como principal del RBAC).
|
|
115
|
+
// Los requests van como clase (class-validator); las responses como tipo.
|
|
116
|
+
__exportStar(require("./dtos/CreateIntegrationRequest"), exports);
|
|
117
|
+
__exportStar(require("./dtos/UpdateIntegrationRequest"), exports);
|
package/package.json
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { IsEmail, IsOptional, IsString } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Request interno (api-invoker) para registrar un email y disparar su verificación.
|
|
6
|
+
* `directoryId` es @IsString (cognitoSub UUID v7 — no usar @IsUUID).
|
|
7
|
+
*/
|
|
8
|
+
export class EmailStartByDirectoryRequest {
|
|
9
|
+
@Expose()
|
|
10
|
+
@IsString()
|
|
11
|
+
directoryId!: string;
|
|
12
|
+
|
|
13
|
+
@Expose()
|
|
14
|
+
@IsEmail()
|
|
15
|
+
email!: string;
|
|
16
|
+
|
|
17
|
+
/** Nombre para el saludo del correo. Default "Cliente". */
|
|
18
|
+
@Expose()
|
|
19
|
+
@IsOptional()
|
|
20
|
+
@IsString()
|
|
21
|
+
name?: string;
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { EmailVerificationStatusEnum } from '../../enums/EmailVerificationStatusEnum';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Response interno del alta + disparo de verificación de un email por directorio.
|
|
6
|
+
*/
|
|
7
|
+
export class EmailStartByDirectoryResponse {
|
|
8
|
+
@Expose()
|
|
9
|
+
email!: string;
|
|
10
|
+
|
|
11
|
+
@Expose()
|
|
12
|
+
verificationId!: string;
|
|
13
|
+
|
|
14
|
+
@Expose()
|
|
15
|
+
status!: EmailVerificationStatusEnum;
|
|
16
|
+
}
|
|
@@ -17,3 +17,5 @@ export * from './dtos/internal/PrimaryEmailByDirectoryRequest';
|
|
|
17
17
|
export * from './dtos/internal/PrimaryEmailResponse';
|
|
18
18
|
export * from './dtos/internal/EmailsByDirectoryRequest';
|
|
19
19
|
export * from './dtos/internal/EmailsByDirectoryResponse';
|
|
20
|
+
export * from './dtos/internal/EmailStartByDirectoryRequest';
|
|
21
|
+
export * from './dtos/internal/EmailStartByDirectoryResponse';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { ArrayNotEmpty, IsArray, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Body del POST /platform/tenants/{tenantId}/integrations. `tenantId` viaja en el path.
|
|
6
|
+
*
|
|
7
|
+
* Da de alta una integración M2M con un socio externo (DEC-RBAC-120/121). Los datos son del tenant
|
|
8
|
+
* pero **solo un usuario de plataforma** puede crearla.
|
|
9
|
+
*
|
|
10
|
+
* `roleId` es un rol del silo del tenant, elegido de los que ya existen — no se siembra uno
|
|
11
|
+
* especial. Está sujeto a las guardas anti-escalada: no puede contener permisos de administración
|
|
12
|
+
* de integraciones ni calcular scope PLATFORM (DEC-RBAC-122/126).
|
|
13
|
+
*
|
|
14
|
+
* `ipAllowlist` es OPCIONAL y su semántica es permisiva (spec §5): ausente, vacía o `['*']` ⇒ sin
|
|
15
|
+
* restricción de IP. Que se pueda apagar es deliberado; que se apague en silencio, no — por eso la
|
|
16
|
+
* pantalla marca las integraciones sin restricción.
|
|
17
|
+
*/
|
|
18
|
+
export class CreateIntegrationRequest {
|
|
19
|
+
@Expose() @IsString() @IsNotEmpty() displayName!: string;
|
|
20
|
+
@Expose() @IsString() @IsNotEmpty() roleId!: string;
|
|
21
|
+
@Expose() @IsOptional() @IsArray() @ArrayNotEmpty() @IsString({ each: true }) ipAllowlist?: string[];
|
|
22
|
+
/** cognitoSub del operador real (audit + grantedBy del assignment). */
|
|
23
|
+
@Expose() @IsString() @IsNotEmpty() createdBy!: string;
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Estado de una llave. NO existe `ROTATING`: rotar es emitir una segunda llave y revocar la vieja,
|
|
3
|
+
* con las dos activas mientras dura la migración del socio.
|
|
4
|
+
*/
|
|
5
|
+
export type IntegrationKeyStatusValue = 'ACTIVE' | 'REVOKED';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Una llave, tal como la devuelve el listado.
|
|
9
|
+
*
|
|
10
|
+
* 🔴 **NUNCA lleva el secreto ni el `secretHash`.** El secreto en claro se devuelve exactamente una
|
|
11
|
+
* vez, en la respuesta del POST que lo emite (`IssueIntegrationKeyResponse`), y no existe ningún
|
|
12
|
+
* endpoint que lo lea de vuelta.
|
|
13
|
+
*
|
|
14
|
+
* `lastUsedAt` y `lastUsedIp` los escribe el authorizer W5, con throttle: sirven para detectar una
|
|
15
|
+
* integración que dejó de llamar, que es uno de los dos incidentes clásicos de un canal M2M.
|
|
16
|
+
*/
|
|
17
|
+
export interface IntegrationKeyResponse {
|
|
18
|
+
keyId: string;
|
|
19
|
+
integrationId: string;
|
|
20
|
+
status: IntegrationKeyStatusValue;
|
|
21
|
+
/** epoch ms. Ausente = no vence. */
|
|
22
|
+
expiresAt?: number;
|
|
23
|
+
lastUsedAt?: number;
|
|
24
|
+
lastUsedIp?: string;
|
|
25
|
+
createdAt: number;
|
|
26
|
+
createdBy?: string;
|
|
27
|
+
revokedAt?: number;
|
|
28
|
+
revokedBy?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Respuesta del POST que emite una llave. **El único lugar de todo el sistema donde el secreto
|
|
33
|
+
* viaja en claro.**
|
|
34
|
+
*
|
|
35
|
+
* Quien lo consuma tiene que mostrarlo una sola vez y no persistirlo: no hay forma de recuperarlo
|
|
36
|
+
* después, porque en base solo queda su hash. Si se pierde, se emite otra llave.
|
|
37
|
+
*/
|
|
38
|
+
export interface IssueIntegrationKeyResponse extends IntegrationKeyResponse {
|
|
39
|
+
/** `fdo_sk.<keyId>.<secreto>` — se muestra UNA vez y no se vuelve a poder leer. */
|
|
40
|
+
token: string;
|
|
41
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Estado de una integración. Suspender corta TODAS sus llaves de una. */
|
|
2
|
+
export type IntegrationStatusValue = 'ACTIVE' | 'SUSPENDED';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Una integración, tal como la devuelven el GET de detalle y el listado.
|
|
6
|
+
*
|
|
7
|
+
* NO lleva nada del secreto de sus llaves — ni el valor ni el hash. Para eso está
|
|
8
|
+
* `IntegrationKeyResponse`, que tampoco los lleva.
|
|
9
|
+
*/
|
|
10
|
+
export interface IntegrationResponse {
|
|
11
|
+
integrationId: string;
|
|
12
|
+
tenantId: string;
|
|
13
|
+
displayName: string;
|
|
14
|
+
status: IntegrationStatusValue;
|
|
15
|
+
/** Rol del silo que porta esta integración. */
|
|
16
|
+
roleId: string;
|
|
17
|
+
/**
|
|
18
|
+
* CIDRs permitidos. Vacío o `['*']` ⇒ **sin restricción de IP** (spec §5).
|
|
19
|
+
* El front lo marca visiblemente en la lista: la protección se puede apagar, pero no en silencio.
|
|
20
|
+
*/
|
|
21
|
+
ipAllowlist: string[];
|
|
22
|
+
createdAt: number;
|
|
23
|
+
updatedAt: number;
|
|
24
|
+
createdBy?: string;
|
|
25
|
+
updatedBy?: string;
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Respuesta del endpoint de diagnóstico del authorizer W5.
|
|
3
|
+
*
|
|
4
|
+
* Devuelve **el principal ya resuelto**, no un "ok". Eso es lo que lo hace útil como prueba de la
|
|
5
|
+
* cadena completa: no verifica que el request pase, sino que haya resuelto como quien debía —
|
|
6
|
+
* con el tenant correcto y con los permisos que su rol otorga.
|
|
7
|
+
*
|
|
8
|
+
* 🔴 Endpoint TEMPORAL, solo dev: expone la lista de permisos del principal. Se saca antes de
|
|
9
|
+
* producción (el permiso `tenant.integration.diagnostic` en cambio se queda, marcado deprecado:
|
|
10
|
+
* quitarlo del enum rompería la cobertura bidireccional del catálogo y dejaría
|
|
11
|
+
* `UnknownPermissionError` en cualquier rol ya sembrado con él).
|
|
12
|
+
*/
|
|
13
|
+
export interface IntegrationWhoamiResponse {
|
|
14
|
+
principalType: 'INTEGRATION';
|
|
15
|
+
/** Con prefijo `INT#`. */
|
|
16
|
+
principalId: string;
|
|
17
|
+
integrationId: string;
|
|
18
|
+
tenantId: string;
|
|
19
|
+
/** Los permisos que resolvió el RBAC para este principal — el punto de la prueba. */
|
|
20
|
+
permissions: string[];
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { ArrayNotEmpty, IsArray, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Body del PUT /platform/tenants/{tenantId}/integrations/{integrationId}.
|
|
6
|
+
*
|
|
7
|
+
* ⚠️ **Semántica de MERGE, no de reemplazo**: solo se actualiza lo que venga. Un campo ausente se
|
|
8
|
+
* deja como está, NO se borra.
|
|
9
|
+
*
|
|
10
|
+
* Es PUT y no PATCH porque `PATCH` no existe en este stack — el enum `HttpMethod` del
|
|
11
|
+
* `@fiado/gateway-adapter` tiene GET/POST/PUT/DELETE, y el CORS y los `GatewayResponses` tampoco lo
|
|
12
|
+
* listan. Mismo precedente que `backofficeUpdateTenantUserField`.
|
|
13
|
+
*
|
|
14
|
+
* El merge no es cosmético: con reemplazo total, un body que omitiera `ipAllowlist` la borraría, y
|
|
15
|
+
* eso apagaría el filtro por IP de la integración sin que nadie lo pidiera.
|
|
16
|
+
*/
|
|
17
|
+
export class UpdateIntegrationRequest {
|
|
18
|
+
@Expose() @IsOptional() @IsString() @IsNotEmpty() displayName?: string;
|
|
19
|
+
@Expose() @IsOptional() @IsArray() @ArrayNotEmpty() @IsString({ each: true }) ipAllowlist?: string[];
|
|
20
|
+
@Expose() @IsString() @IsNotEmpty() updatedBy!: string;
|
|
21
|
+
}
|
|
@@ -146,6 +146,23 @@ export enum Permission {
|
|
|
146
146
|
LEVEL3_ROLE_ASSIGN = 'level3.role.assign',
|
|
147
147
|
LEVEL3_ROLE_REVOKE = 'level3.role.revoke',
|
|
148
148
|
LEVEL3_AUDIT_VIEW = 'level3.audit.view',
|
|
149
|
+
|
|
150
|
+
// Append-only 2026-08-10 (DEC-RBAC-120/121/126): integraciones M2M con socios externos.
|
|
151
|
+
// Los cuatro de ADMINISTRACIÓN son scope PLATFORM: los datos de la integración son del tenant,
|
|
152
|
+
// pero solo un usuario de plataforma la crea, rota o revoca. Son además el set exacto que la
|
|
153
|
+
// guarda 1 prohíbe asignarle a un principal `INT#` — una integración jamás puede administrarse
|
|
154
|
+
// a sí misma.
|
|
155
|
+
PLATFORM_INTEGRATION_VIEW = 'platform.integration.view',
|
|
156
|
+
PLATFORM_INTEGRATION_MANAGE = 'platform.integration.manage',
|
|
157
|
+
PLATFORM_INTEGRATION_KEY_ISSUE = 'platform.integration.key.issue',
|
|
158
|
+
PLATFORM_INTEGRATION_KEY_REVOKE = 'platform.integration.key.revoke',
|
|
159
|
+
|
|
160
|
+
// DEC-RBAC-126: el endpoint de diagnóstico del authorizer W5 lo llama la INTEGRACIÓN, no un
|
|
161
|
+
// humano — y una integración NUNCA puede portar permisos de scope PLATFORM (computeRoleScope
|
|
162
|
+
// toma el MAX de los scopes del rol, así que uno solo lo volvería PLATFORM con scopeRef '*').
|
|
163
|
+
// Por eso este es TENANT-scoped. Y por eso NO entra en el set de la guarda 1: no administra
|
|
164
|
+
// nada, solo devuelve quién sos.
|
|
165
|
+
TENANT_INTEGRATION_DIAGNOSTIC = 'tenant.integration.diagnostic',
|
|
149
166
|
}
|
|
150
167
|
|
|
151
168
|
/**
|
|
@@ -259,6 +276,13 @@ export const PERMISSION_BIT_ORDER: readonly Permission[] = [
|
|
|
259
276
|
Permission.LEVEL3_ROLE_ASSIGN,
|
|
260
277
|
Permission.LEVEL3_ROLE_REVOKE,
|
|
261
278
|
Permission.LEVEL3_AUDIT_VIEW,
|
|
279
|
+
// Append-only 2026-08-10 (DEC-RBAC-120/126): integraciones M2M. Van AL FINAL y en este orden,
|
|
280
|
+
// nunca intercalados: reordenar desalinearía los bits de los tokens ya emitidos.
|
|
281
|
+
Permission.PLATFORM_INTEGRATION_VIEW,
|
|
282
|
+
Permission.PLATFORM_INTEGRATION_MANAGE,
|
|
283
|
+
Permission.PLATFORM_INTEGRATION_KEY_ISSUE,
|
|
284
|
+
Permission.PLATFORM_INTEGRATION_KEY_REVOKE,
|
|
285
|
+
Permission.TENANT_INTEGRATION_DIAGNOSTIC,
|
|
262
286
|
] as const;
|
|
263
287
|
|
|
264
288
|
function djb2(input: string): number {
|
|
@@ -138,3 +138,15 @@ export * from './dtos/CreateLevelEntityRequest';
|
|
|
138
138
|
export type { CreateLevelEntityResponse } from './dtos/CreateLevelEntityResponse';
|
|
139
139
|
export * from './dtos/CreateTenantUserRequest';
|
|
140
140
|
export type { CreateTenantUserResponse } from './dtos/CreateTenantUserResponse';
|
|
141
|
+
|
|
142
|
+
// DEC-RBAC-120/121/126: integraciones M2M con socios externos (API keys como principal del RBAC).
|
|
143
|
+
// Los requests van como clase (class-validator); las responses como tipo.
|
|
144
|
+
export * from './dtos/CreateIntegrationRequest';
|
|
145
|
+
export * from './dtos/UpdateIntegrationRequest';
|
|
146
|
+
export type { IntegrationResponse, IntegrationStatusValue } from './dtos/IntegrationResponse';
|
|
147
|
+
export type {
|
|
148
|
+
IntegrationKeyResponse,
|
|
149
|
+
IntegrationKeyStatusValue,
|
|
150
|
+
IssueIntegrationKeyResponse,
|
|
151
|
+
} from './dtos/IntegrationKeyResponse';
|
|
152
|
+
export type { IntegrationWhoamiResponse } from './dtos/IntegrationWhoamiResponse';
|