@fiado/type-kit 3.209.0 → 3.211.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/kyc/KycVerificationChangedV1.test.ts +57 -1
- package/bin/kyc/dtos/KycSubChecks.d.ts +37 -0
- package/bin/kyc/dtos/KycSubChecks.js +84 -0
- package/bin/kyc/enums/KycSubCheckStatusEnum.d.ts +15 -0
- package/bin/kyc/enums/KycSubCheckStatusEnum.js +19 -0
- package/bin/kyc/enums/KycWatchlistStatusEnum.d.ts +16 -0
- package/bin/kyc/enums/KycWatchlistStatusEnum.js +20 -0
- package/bin/kyc/events/KycVerificationChangedV1.d.ts +12 -2
- package/bin/kyc/events/KycVerificationChangedV1.js +10 -2
- package/bin/kyc/index.d.ts +3 -0
- package/bin/kyc/index.js +4 -0
- package/bin/loanCredit/dtos/LoanBorrower.d.ts +5 -2
- package/bin/loanCredit/dtos/LoanBorrower.js +1 -2
- package/bin/loanCredit/dtos/requests/SignLoanCreditRequest.d.ts +2 -2
- package/bin/loanCredit/dtos/requests/UpsertLoanBorrowerRequest.d.ts +11 -9
- package/bin/loanCredit/dtos/requests/UpsertLoanBorrowerRequest.js +10 -30
- package/bin/loanCredit/dtos/responses/LoanBorrowerResponse.d.ts +1 -1
- package/package.json +1 -1
- package/src/kyc/dtos/KycSubChecks.ts +55 -0
- package/src/kyc/enums/KycSubCheckStatusEnum.ts +15 -0
- package/src/kyc/enums/KycWatchlistStatusEnum.ts +16 -0
- package/src/kyc/events/KycVerificationChangedV1.ts +16 -4
- package/src/kyc/index.ts +5 -0
- package/src/loanCredit/dtos/LoanBorrower.ts +5 -3
- package/src/loanCredit/dtos/requests/SignLoanCreditRequest.ts +2 -2
- package/src/loanCredit/dtos/requests/UpsertLoanBorrowerRequest.ts +12 -37
- package/src/loanCredit/dtos/responses/LoanBorrowerResponse.ts +1 -1
- package/bin/benefitCenter/enums/BenefitFlowEnum.d.ts +0 -11
- package/bin/benefitCenter/enums/BenefitFlowEnum.js +0 -15
- package/bin/walletFunding/dtos/CancelFundingReferenceRequest.d.ts +0 -6
- package/bin/walletFunding/dtos/CancelFundingReferenceRequest.js +0 -31
- package/bin/walletFunding/dtos/CancelFundingReferenceResponse.d.ts +0 -7
- package/bin/walletFunding/dtos/CancelFundingReferenceResponse.js +0 -6
- package/bin/walletFunding/dtos/CancelFundingRequest.d.ts +0 -11
- package/bin/walletFunding/dtos/CancelFundingRequest.js +0 -33
- package/bin/walletFunding/dtos/CancelFundingResponse.d.ts +0 -14
- package/bin/walletFunding/dtos/CancelFundingResponse.js +0 -12
- package/bin/walletFunding/dtos/CancelWalletFundingRequest.d.ts +0 -3
- package/bin/walletFunding/dtos/CancelWalletFundingRequest.js +0 -21
- package/bin/walletFunding/dtos/CancelWalletFundingResponse.d.ts +0 -7
- package/bin/walletFunding/dtos/CancelWalletFundingResponse.js +0 -6
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
2
|
import { plainToInstance } from 'class-transformer';
|
|
3
3
|
import { validate } from 'class-validator';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
KycVerificationChangedV1,
|
|
6
|
+
KycSubCheckStatusEnum,
|
|
7
|
+
KycWatchlistStatusEnum,
|
|
8
|
+
} from '../../../src/kyc/index';
|
|
5
9
|
|
|
6
10
|
describe('KycVerificationChangedV1', () => {
|
|
7
11
|
it('valida el shape que produce el Pipe desde el NewImage', async () => {
|
|
@@ -83,6 +87,58 @@ describe('KycVerificationChangedV1', () => {
|
|
|
83
87
|
expect(errors.map((e) => e.property)).toContain('verificationResult');
|
|
84
88
|
});
|
|
85
89
|
|
|
90
|
+
// SureKeep F2 — subChecks. ADITIVO: un mensaje sin subChecks (el shape que hoy publica el
|
|
91
|
+
// webhook antes de este cambio) DEBE seguir validando. Sin este candado se podría marcar
|
|
92
|
+
// subChecks como requerido y romper la compatibilidad hacia atrás.
|
|
93
|
+
it('valida un mensaje SIN subChecks (compatibilidad hacia atrás)', async () => {
|
|
94
|
+
const raw = {
|
|
95
|
+
verificationId: 'ver-1', directoryId: 'dir-1', peopleId: 'ppl-1',
|
|
96
|
+
verificationStatus: 'COMPLETED', verificationResult: 'VERIFIED',
|
|
97
|
+
updateDate: '2026-07-21T10:05:00.000Z',
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const dto = plainToInstance(KycVerificationChangedV1, raw, { excludeExtraneousValues: true });
|
|
101
|
+
|
|
102
|
+
expect(await validate(dto as object)).toHaveLength(0);
|
|
103
|
+
expect(dto.subChecks).toBeUndefined();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('acepta y tipa los 8 subChecks, con CLEAR/HIT distinto de PASS/FAIL', async () => {
|
|
107
|
+
const raw = {
|
|
108
|
+
verificationId: 'ver-1', directoryId: 'dir-1', peopleId: 'ppl-1',
|
|
109
|
+
verificationStatus: 'COMPLETED', verificationResult: 'VERIFIED',
|
|
110
|
+
updateDate: '2026-07-21T10:05:00.000Z',
|
|
111
|
+
subChecks: {
|
|
112
|
+
documentReading: 'PASS', templateMatching: 'PASS', alterationDetection: 'PASS',
|
|
113
|
+
facematch: 'PASS', liveness: 'PASS', ageCheck: 'PASS',
|
|
114
|
+
watchlists: 'HIT', premiumAmlWatchlists: 'CLEAR',
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const dto = plainToInstance(KycVerificationChangedV1, raw, { excludeExtraneousValues: true });
|
|
119
|
+
|
|
120
|
+
expect(await validate(dto as object)).toHaveLength(0);
|
|
121
|
+
expect(dto.subChecks?.facematch).toBe(KycSubCheckStatusEnum.PASS);
|
|
122
|
+
expect(dto.subChecks?.watchlists).toBe(KycWatchlistStatusEnum.HIT);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Candado del vocabulario: un binario NO acepta HIT y una lista NO acepta PASS. Sin esto,
|
|
126
|
+
// los dos enums podrían colapsar en uno y se perdería el matiz "HIT no es un fallo".
|
|
127
|
+
it('rechaza PASS en una watchlist (una lista es CLEAR/HIT, no PASS/FAIL)', async () => {
|
|
128
|
+
const raw = {
|
|
129
|
+
verificationId: 'ver-1', directoryId: 'dir-1', peopleId: 'ppl-1',
|
|
130
|
+
verificationStatus: 'COMPLETED', verificationResult: 'VERIFIED',
|
|
131
|
+
updateDate: '2026-07-21T10:05:00.000Z',
|
|
132
|
+
subChecks: { watchlists: 'PASS' },
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const dto = plainToInstance(KycVerificationChangedV1, raw, { excludeExtraneousValues: true });
|
|
136
|
+
const errors = await validate(dto as object);
|
|
137
|
+
|
|
138
|
+
const nested = errors.find((e) => e.property === 'subChecks');
|
|
139
|
+
expect(nested?.children?.some((c) => c.property === 'watchlists')).toBe(true);
|
|
140
|
+
});
|
|
141
|
+
|
|
86
142
|
// El consumidor ordena por updateDate (spec §6): sin @IsISO8601() el orden es una asunción.
|
|
87
143
|
it('rechaza updateDate con formato no ISO-8601', async () => {
|
|
88
144
|
const raw = {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { KycSubCheckStatusEnum } from '../enums/KycSubCheckStatusEnum';
|
|
2
|
+
import { KycWatchlistStatusEnum } from '../enums/KycWatchlistStatusEnum';
|
|
3
|
+
/**
|
|
4
|
+
* Los 8 sub-pasos del KYC de Metamap, descompuestos — el resultado de CADA estación, no el
|
|
5
|
+
* veredicto global. Viaja dentro de `KycVerificationChangedV1.subChecks`.
|
|
6
|
+
*
|
|
7
|
+
* **Por qué existe:** hoy el KYC llega como un solo bombillo (VERIFIED/REJECTED). Pero no todo
|
|
8
|
+
* fallo es igual: un facematch fallido es fraude, un hit de watchlist es "que lo mire cumplimiento",
|
|
9
|
+
* una mala foto es un reintento. Descomponerlo deja que SureKeep aplique una política por sub-paso.
|
|
10
|
+
*
|
|
11
|
+
* **El webhook los produce como TRADUCTOR, no como juez:** deriva cada uno de la presencia de
|
|
12
|
+
* `error` en el `step_completed` de Metamap. NO decide qué significa el fallo para la venta —
|
|
13
|
+
* esa política vive del lado de SureKeep (consolidación / oficial de cumplimiento).
|
|
14
|
+
*
|
|
15
|
+
* **Todos opcionales:** un flujo de Metamap puede no correr todas las estaciones. Un campo ausente
|
|
16
|
+
* significa "esa estación no corrió en este flujo", distinto de un `FAIL`.
|
|
17
|
+
*
|
|
18
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
19
|
+
*/
|
|
20
|
+
export declare class KycSubChecks {
|
|
21
|
+
/** ¿Se leyó bien el documento? Mala foto → FAIL (reintento). */
|
|
22
|
+
documentReading?: KycSubCheckStatusEnum;
|
|
23
|
+
/** ¿El documento es una plantilla válida (una INE de verdad)? */
|
|
24
|
+
templateMatching?: KycSubCheckStatusEnum;
|
|
25
|
+
/** ¿El documento fue alterado/photoshopeado? FAIL = detectó alteración. */
|
|
26
|
+
alterationDetection?: KycSubCheckStatusEnum;
|
|
27
|
+
/** ¿La cara de la selfie coincide con la del documento? FAIL = no coincide (suplantación). */
|
|
28
|
+
facematch?: KycSubCheckStatusEnum;
|
|
29
|
+
/** ¿Es una persona viva frente a la cámara y no una foto de una foto? FAIL = no vivo. */
|
|
30
|
+
liveness?: KycSubCheckStatusEnum;
|
|
31
|
+
/** ¿Tiene 18 o más? FAIL = menor de edad. */
|
|
32
|
+
ageCheck?: KycSubCheckStatusEnum;
|
|
33
|
+
/** ¿Apareció en una watchlist? HIT = apareció → oficial de cumplimiento (NO es rechazo). */
|
|
34
|
+
watchlists?: KycWatchlistStatusEnum;
|
|
35
|
+
/** ¿Apareció en una lista premium (PEP/sanciones)? HIT → oficial de cumplimiento. */
|
|
36
|
+
premiumAmlWatchlists?: KycWatchlistStatusEnum;
|
|
37
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
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.KycSubChecks = void 0;
|
|
13
|
+
const class_transformer_1 = require("class-transformer");
|
|
14
|
+
const class_validator_1 = require("class-validator");
|
|
15
|
+
const KycSubCheckStatusEnum_1 = require("../enums/KycSubCheckStatusEnum");
|
|
16
|
+
const KycWatchlistStatusEnum_1 = require("../enums/KycWatchlistStatusEnum");
|
|
17
|
+
/**
|
|
18
|
+
* Los 8 sub-pasos del KYC de Metamap, descompuestos — el resultado de CADA estación, no el
|
|
19
|
+
* veredicto global. Viaja dentro de `KycVerificationChangedV1.subChecks`.
|
|
20
|
+
*
|
|
21
|
+
* **Por qué existe:** hoy el KYC llega como un solo bombillo (VERIFIED/REJECTED). Pero no todo
|
|
22
|
+
* fallo es igual: un facematch fallido es fraude, un hit de watchlist es "que lo mire cumplimiento",
|
|
23
|
+
* una mala foto es un reintento. Descomponerlo deja que SureKeep aplique una política por sub-paso.
|
|
24
|
+
*
|
|
25
|
+
* **El webhook los produce como TRADUCTOR, no como juez:** deriva cada uno de la presencia de
|
|
26
|
+
* `error` en el `step_completed` de Metamap. NO decide qué significa el fallo para la venta —
|
|
27
|
+
* esa política vive del lado de SureKeep (consolidación / oficial de cumplimiento).
|
|
28
|
+
*
|
|
29
|
+
* **Todos opcionales:** un flujo de Metamap puede no correr todas las estaciones. Un campo ausente
|
|
30
|
+
* significa "esa estación no corrió en este flujo", distinto de un `FAIL`.
|
|
31
|
+
*
|
|
32
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
33
|
+
*/
|
|
34
|
+
class KycSubChecks {
|
|
35
|
+
}
|
|
36
|
+
exports.KycSubChecks = KycSubChecks;
|
|
37
|
+
__decorate([
|
|
38
|
+
(0, class_transformer_1.Expose)(),
|
|
39
|
+
(0, class_validator_1.IsOptional)(),
|
|
40
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
41
|
+
__metadata("design:type", String)
|
|
42
|
+
], KycSubChecks.prototype, "documentReading", void 0);
|
|
43
|
+
__decorate([
|
|
44
|
+
(0, class_transformer_1.Expose)(),
|
|
45
|
+
(0, class_validator_1.IsOptional)(),
|
|
46
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
47
|
+
__metadata("design:type", String)
|
|
48
|
+
], KycSubChecks.prototype, "templateMatching", void 0);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, class_transformer_1.Expose)(),
|
|
51
|
+
(0, class_validator_1.IsOptional)(),
|
|
52
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
53
|
+
__metadata("design:type", String)
|
|
54
|
+
], KycSubChecks.prototype, "alterationDetection", void 0);
|
|
55
|
+
__decorate([
|
|
56
|
+
(0, class_transformer_1.Expose)(),
|
|
57
|
+
(0, class_validator_1.IsOptional)(),
|
|
58
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
59
|
+
__metadata("design:type", String)
|
|
60
|
+
], KycSubChecks.prototype, "facematch", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
(0, class_transformer_1.Expose)(),
|
|
63
|
+
(0, class_validator_1.IsOptional)(),
|
|
64
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
65
|
+
__metadata("design:type", String)
|
|
66
|
+
], KycSubChecks.prototype, "liveness", void 0);
|
|
67
|
+
__decorate([
|
|
68
|
+
(0, class_transformer_1.Expose)(),
|
|
69
|
+
(0, class_validator_1.IsOptional)(),
|
|
70
|
+
(0, class_validator_1.IsEnum)(KycSubCheckStatusEnum_1.KycSubCheckStatusEnum),
|
|
71
|
+
__metadata("design:type", String)
|
|
72
|
+
], KycSubChecks.prototype, "ageCheck", void 0);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, class_transformer_1.Expose)(),
|
|
75
|
+
(0, class_validator_1.IsOptional)(),
|
|
76
|
+
(0, class_validator_1.IsEnum)(KycWatchlistStatusEnum_1.KycWatchlistStatusEnum),
|
|
77
|
+
__metadata("design:type", String)
|
|
78
|
+
], KycSubChecks.prototype, "watchlists", void 0);
|
|
79
|
+
__decorate([
|
|
80
|
+
(0, class_transformer_1.Expose)(),
|
|
81
|
+
(0, class_validator_1.IsOptional)(),
|
|
82
|
+
(0, class_validator_1.IsEnum)(KycWatchlistStatusEnum_1.KycWatchlistStatusEnum),
|
|
83
|
+
__metadata("design:type", String)
|
|
84
|
+
], KycSubChecks.prototype, "premiumAmlWatchlists", void 0);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resultado de un sub-paso BINARIO del KYC (los que pasan o fallan sin matices).
|
|
3
|
+
*
|
|
4
|
+
* El webhook lo deriva de la presencia/ausencia de `error` en el `step_completed` de Metamap:
|
|
5
|
+
* sin error → `PASS`, con error → `FAIL`. No hay tri-estado en estos.
|
|
6
|
+
*
|
|
7
|
+
* Aplica a: document-reading, template-matching, alteration-detection, facematch, liveness, age-check.
|
|
8
|
+
* (Las listas de watchlist usan `KycWatchlistStatusEnum` — un hit NO es un fallo.)
|
|
9
|
+
*
|
|
10
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
11
|
+
*/
|
|
12
|
+
export declare enum KycSubCheckStatusEnum {
|
|
13
|
+
PASS = "PASS",
|
|
14
|
+
FAIL = "FAIL"
|
|
15
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KycSubCheckStatusEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Resultado de un sub-paso BINARIO del KYC (los que pasan o fallan sin matices).
|
|
6
|
+
*
|
|
7
|
+
* El webhook lo deriva de la presencia/ausencia de `error` en el `step_completed` de Metamap:
|
|
8
|
+
* sin error → `PASS`, con error → `FAIL`. No hay tri-estado en estos.
|
|
9
|
+
*
|
|
10
|
+
* Aplica a: document-reading, template-matching, alteration-detection, facematch, liveness, age-check.
|
|
11
|
+
* (Las listas de watchlist usan `KycWatchlistStatusEnum` — un hit NO es un fallo.)
|
|
12
|
+
*
|
|
13
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
14
|
+
*/
|
|
15
|
+
var KycSubCheckStatusEnum;
|
|
16
|
+
(function (KycSubCheckStatusEnum) {
|
|
17
|
+
KycSubCheckStatusEnum["PASS"] = "PASS";
|
|
18
|
+
KycSubCheckStatusEnum["FAIL"] = "FAIL";
|
|
19
|
+
})(KycSubCheckStatusEnum || (exports.KycSubCheckStatusEnum = KycSubCheckStatusEnum = {}));
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resultado de un sub-paso de LISTA del KYC (watchlists, premium-aml-watchlists).
|
|
3
|
+
*
|
|
4
|
+
* Deliberadamente NO reusa `KycSubCheckStatusEnum`: un `HIT` en una lista **no es un fallo**.
|
|
5
|
+
* Es un "que lo mire un humano" — el cliente aparece en una lista y un oficial de cumplimiento (D21)
|
|
6
|
+
* decide, en vez de rechazar automáticamente. Ese matiz es justo lo que el vocabulario binario
|
|
7
|
+
* pasado por alto perdía: si `HIT` fuera `FAIL`, la venta se bloquearía sola sin revisión.
|
|
8
|
+
*
|
|
9
|
+
* `CLEAR` = no apareció en ninguna lista. `HIT` = apareció, requiere revisión de cumplimiento.
|
|
10
|
+
*
|
|
11
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
12
|
+
*/
|
|
13
|
+
export declare enum KycWatchlistStatusEnum {
|
|
14
|
+
CLEAR = "CLEAR",
|
|
15
|
+
HIT = "HIT"
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.KycWatchlistStatusEnum = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Resultado de un sub-paso de LISTA del KYC (watchlists, premium-aml-watchlists).
|
|
6
|
+
*
|
|
7
|
+
* Deliberadamente NO reusa `KycSubCheckStatusEnum`: un `HIT` en una lista **no es un fallo**.
|
|
8
|
+
* Es un "que lo mire un humano" — el cliente aparece en una lista y un oficial de cumplimiento (D21)
|
|
9
|
+
* decide, en vez de rechazar automáticamente. Ese matiz es justo lo que el vocabulario binario
|
|
10
|
+
* pasado por alto perdía: si `HIT` fuera `FAIL`, la venta se bloquearía sola sin revisión.
|
|
11
|
+
*
|
|
12
|
+
* `CLEAR` = no apareció en ninguna lista. `HIT` = apareció, requiere revisión de cumplimiento.
|
|
13
|
+
*
|
|
14
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
15
|
+
*/
|
|
16
|
+
var KycWatchlistStatusEnum;
|
|
17
|
+
(function (KycWatchlistStatusEnum) {
|
|
18
|
+
KycWatchlistStatusEnum["CLEAR"] = "CLEAR";
|
|
19
|
+
KycWatchlistStatusEnum["HIT"] = "HIT";
|
|
20
|
+
})(KycWatchlistStatusEnum || (exports.KycWatchlistStatusEnum = KycWatchlistStatusEnum = {}));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { IdentificationDocumentStatus } from '../../identity/enums/IdentificationDocumentStatus';
|
|
2
2
|
import { KycVerificationStatusEnum } from '../enums/KycVerificationStatusEnum';
|
|
3
|
+
import { KycSubChecks } from '../dtos/KycSubChecks';
|
|
3
4
|
/**
|
|
4
|
-
* Cambio terminal de una verificación KYC, tal como
|
|
5
|
-
* `
|
|
5
|
+
* Cambio terminal de una verificación KYC, tal como lo publica `kyc-metamap-webhook` directo en
|
|
6
|
+
* `RetailKycInboundQueue` (el webhook manda un `SendMessage` cuando la verificación pasa a COMPLETED).
|
|
6
7
|
*
|
|
7
8
|
* NO lleva `tenantId`: el de la tabla es un valor hardcodeado que no discrimina silo.
|
|
8
9
|
* La pertenencia se resuelve en el consumer con el gate de `WizardSession`.
|
|
@@ -32,4 +33,13 @@ export declare class KycVerificationChangedV1 {
|
|
|
32
33
|
* (ejemplo real: '2025-10-06T21:40:58.277Z'). Verificado, no asumido (2026-07-21).
|
|
33
34
|
*/
|
|
34
35
|
updateDate: string;
|
|
36
|
+
/**
|
|
37
|
+
* Los 8 sub-pasos descompuestos (SureKeep F2). OPCIONAL y aditivo: un mensaje viejo sin
|
|
38
|
+
* `subChecks` sigue validando, y un consumidor que aún no aplica política los ignora sin romperse.
|
|
39
|
+
*
|
|
40
|
+
* El webhook los produce como traductor (error del `step_completed` → PASS/FAIL, o CLEAR/HIT
|
|
41
|
+
* para las listas). La POLÍTICA de qué hacer con cada uno (facematch FAIL → rechazo, watchlist
|
|
42
|
+
* HIT → oficial de cumplimiento, mala foto → reintento) vive del lado de SureKeep, NO aquí.
|
|
43
|
+
*/
|
|
44
|
+
subChecks?: KycSubChecks;
|
|
35
45
|
}
|
|
@@ -14,9 +14,10 @@ const class_transformer_1 = require("class-transformer");
|
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
15
|
const IdentificationDocumentStatus_1 = require("../../identity/enums/IdentificationDocumentStatus");
|
|
16
16
|
const KycVerificationStatusEnum_1 = require("../enums/KycVerificationStatusEnum");
|
|
17
|
+
const KycSubChecks_1 = require("../dtos/KycSubChecks");
|
|
17
18
|
/**
|
|
18
|
-
* Cambio terminal de una verificación KYC, tal como
|
|
19
|
-
* `
|
|
19
|
+
* Cambio terminal de una verificación KYC, tal como lo publica `kyc-metamap-webhook` directo en
|
|
20
|
+
* `RetailKycInboundQueue` (el webhook manda un `SendMessage` cuando la verificación pasa a COMPLETED).
|
|
20
21
|
*
|
|
21
22
|
* NO lleva `tenantId`: el de la tabla es un valor hardcodeado que no discrimina silo.
|
|
22
23
|
* La pertenencia se resuelve en el consumer con el gate de `WizardSession`.
|
|
@@ -74,3 +75,10 @@ __decorate([
|
|
|
74
75
|
(0, class_validator_1.IsISO8601)(),
|
|
75
76
|
__metadata("design:type", String)
|
|
76
77
|
], KycVerificationChangedV1.prototype, "updateDate", void 0);
|
|
78
|
+
__decorate([
|
|
79
|
+
(0, class_transformer_1.Expose)(),
|
|
80
|
+
(0, class_validator_1.IsOptional)(),
|
|
81
|
+
(0, class_validator_1.ValidateNested)(),
|
|
82
|
+
(0, class_transformer_1.Type)(() => KycSubChecks_1.KycSubChecks),
|
|
83
|
+
__metadata("design:type", KycSubChecks_1.KycSubChecks)
|
|
84
|
+
], KycVerificationChangedV1.prototype, "subChecks", void 0);
|
package/bin/kyc/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export * from './enums/KycVerificationStatusEnum';
|
|
2
|
+
export * from './enums/KycSubCheckStatusEnum';
|
|
3
|
+
export * from './enums/KycWatchlistStatusEnum';
|
|
4
|
+
export * from './dtos/KycSubChecks';
|
|
2
5
|
export * from './dtos/responses/KycPersonData';
|
|
3
6
|
export * from './dtos/responses/KycByDirectoryResponse';
|
|
4
7
|
export * from './events/KycVerificationChangedV1';
|
package/bin/kyc/index.js
CHANGED
|
@@ -17,6 +17,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
// Enums (el consolidado reusa RetailKycStatusEnum del dominio retailCustomer — DEC-KYC-014;
|
|
18
18
|
// `verificationResult` reusa IdentificationDocumentStatus de `identity` — DEC-KYC-016)
|
|
19
19
|
__exportStar(require("./enums/KycVerificationStatusEnum"), exports);
|
|
20
|
+
__exportStar(require("./enums/KycSubCheckStatusEnum"), exports);
|
|
21
|
+
__exportStar(require("./enums/KycWatchlistStatusEnum"), exports);
|
|
22
|
+
// Sub-pasos descompuestos (SureKeep F2)
|
|
23
|
+
__exportStar(require("./dtos/KycSubChecks"), exports);
|
|
20
24
|
// Response DTOs
|
|
21
25
|
__exportStar(require("./dtos/responses/KycPersonData"), exports);
|
|
22
26
|
__exportStar(require("./dtos/responses/KycByDirectoryResponse"), exports);
|
|
@@ -9,8 +9,11 @@ export declare class LoanBorrower {
|
|
|
9
9
|
borrowerId: string;
|
|
10
10
|
/** FK al comprador de retail (`RetailCustomer` — owner retail-customer-business). */
|
|
11
11
|
retailCustomerId: string;
|
|
12
|
-
/**
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* ANCLA canónica del acreditado: el directoryId de Fiado (identidad universal — L-hydrate,
|
|
14
|
+
* decisión 2026-07-22). `retailCustomerId` queda solo como referencia del tenant.
|
|
15
|
+
*/
|
|
16
|
+
directoryId: string;
|
|
14
17
|
/** SCI vigente 0-100 (M7). Ausente hasta la primera evaluación. */
|
|
15
18
|
sciScore?: number;
|
|
16
19
|
clientLevel?: ClientLevelEnum;
|
|
@@ -35,10 +35,9 @@ __decorate([
|
|
|
35
35
|
], LoanBorrower.prototype, "retailCustomerId", void 0);
|
|
36
36
|
__decorate([
|
|
37
37
|
(0, class_transformer_1.Expose)(),
|
|
38
|
-
(0, class_validator_1.IsOptional)(),
|
|
39
38
|
(0, class_validator_1.IsString)(),
|
|
40
39
|
__metadata("design:type", String)
|
|
41
|
-
], LoanBorrower.prototype, "
|
|
40
|
+
], LoanBorrower.prototype, "directoryId", void 0);
|
|
42
41
|
__decorate([
|
|
43
42
|
(0, class_transformer_1.Expose)(),
|
|
44
43
|
(0, class_validator_1.IsOptional)(),
|
|
@@ -16,8 +16,8 @@ export declare class SignLoanCreditRequest {
|
|
|
16
16
|
otpCode?: string;
|
|
17
17
|
/**
|
|
18
18
|
* SOLO en el inicio de firma (tiempo 1) con el OTP REAL de messages-business: el directoryId
|
|
19
|
-
* Fiado del cliente (lo aporta el WIZARD — dueño del dato; fallback: el
|
|
20
|
-
*
|
|
19
|
+
* Fiado del cliente (lo aporta el WIZARD — dueño del dato; fallback: el directoryId
|
|
20
|
+
* (ancla) del borrower). El OTP se genera/verifica keyeado a este id (D5).
|
|
21
21
|
*/
|
|
22
22
|
otpDirectoryId?: string;
|
|
23
23
|
/**
|
|
@@ -1,16 +1,18 @@
|
|
|
1
|
-
import { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
|
|
2
1
|
import { LoanBeneficiary } from '../LoanBeneficiary';
|
|
3
2
|
/**
|
|
4
|
-
* Body de POST /
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Body de `POST /private/borrowers` (loan-credit-business) — ALTA ON-DEMAND del acreditado
|
|
4
|
+
* (paso 04 del wizard, al elegir SureKeep como forma de pago — decisión 2026-07-22, L-hydrate).
|
|
5
|
+
*
|
|
6
|
+
* El wizard solo IDENTIFICA al cliente: el motor hace un pull síncrono a `retail-customer`
|
|
7
|
+
* (`GET /private/customers/:id`), valida `kycStatus=VERIFIED` + identidad Fiado presente, y
|
|
8
|
+
* persiste el acreditado con ancla `directoryId`. La PII del pull es TRANSITORIA (no se guarda).
|
|
9
|
+
*
|
|
10
|
+
* Idempotente: si el acreditado ya existe, se devuelve/completa (una persona = una ficha).
|
|
11
|
+
* Errores: `KYC_NOT_VERIFIED` · `IDENTITY_MISSING` · `BORROWER_SOURCE_NOT_FOUND` ·
|
|
12
|
+
* `RETAIL_PULL_FAILED` (422/502 — ver openapi del motor).
|
|
7
13
|
*/
|
|
8
14
|
export declare class UpsertLoanBorrowerRequest {
|
|
9
15
|
retailCustomerId: string;
|
|
10
|
-
/**
|
|
11
|
-
fiadoDirectoryId?: string;
|
|
12
|
-
sciScore?: number;
|
|
13
|
-
clientLevel?: ClientLevelEnum;
|
|
14
|
-
bureauScore?: number;
|
|
16
|
+
/** Beneficiario / a quién avisar (opcional — el wizard lo captura en su paso propio). */
|
|
15
17
|
beneficiary?: LoanBeneficiary;
|
|
16
18
|
}
|
|
@@ -12,12 +12,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.UpsertLoanBorrowerRequest = void 0;
|
|
13
13
|
const class_transformer_1 = require("class-transformer");
|
|
14
14
|
const class_validator_1 = require("class-validator");
|
|
15
|
-
const ClientLevelEnum_1 = require("../../../loanScoring/enums/ClientLevelEnum");
|
|
16
15
|
const LoanBeneficiary_1 = require("../LoanBeneficiary");
|
|
17
16
|
/**
|
|
18
|
-
* Body de POST /
|
|
19
|
-
*
|
|
20
|
-
*
|
|
17
|
+
* Body de `POST /private/borrowers` (loan-credit-business) — ALTA ON-DEMAND del acreditado
|
|
18
|
+
* (paso 04 del wizard, al elegir SureKeep como forma de pago — decisión 2026-07-22, L-hydrate).
|
|
19
|
+
*
|
|
20
|
+
* El wizard solo IDENTIFICA al cliente: el motor hace un pull síncrono a `retail-customer`
|
|
21
|
+
* (`GET /private/customers/:id`), valida `kycStatus=VERIFIED` + identidad Fiado presente, y
|
|
22
|
+
* persiste el acreditado con ancla `directoryId`. La PII del pull es TRANSITORIA (no se guarda).
|
|
23
|
+
*
|
|
24
|
+
* Idempotente: si el acreditado ya existe, se devuelve/completa (una persona = una ficha).
|
|
25
|
+
* Errores: `KYC_NOT_VERIFIED` · `IDENTITY_MISSING` · `BORROWER_SOURCE_NOT_FOUND` ·
|
|
26
|
+
* `RETAIL_PULL_FAILED` (422/502 — ver openapi del motor).
|
|
21
27
|
*/
|
|
22
28
|
class UpsertLoanBorrowerRequest {
|
|
23
29
|
}
|
|
@@ -28,32 +34,6 @@ __decorate([
|
|
|
28
34
|
(0, class_validator_1.IsNotEmpty)(),
|
|
29
35
|
__metadata("design:type", String)
|
|
30
36
|
], UpsertLoanBorrowerRequest.prototype, "retailCustomerId", void 0);
|
|
31
|
-
__decorate([
|
|
32
|
-
(0, class_transformer_1.Expose)(),
|
|
33
|
-
(0, class_validator_1.IsOptional)(),
|
|
34
|
-
(0, class_validator_1.IsString)(),
|
|
35
|
-
__metadata("design:type", String)
|
|
36
|
-
], UpsertLoanBorrowerRequest.prototype, "fiadoDirectoryId", void 0);
|
|
37
|
-
__decorate([
|
|
38
|
-
(0, class_transformer_1.Expose)(),
|
|
39
|
-
(0, class_validator_1.IsOptional)(),
|
|
40
|
-
(0, class_validator_1.IsInt)(),
|
|
41
|
-
(0, class_validator_1.Min)(0),
|
|
42
|
-
(0, class_validator_1.Max)(100),
|
|
43
|
-
__metadata("design:type", Number)
|
|
44
|
-
], UpsertLoanBorrowerRequest.prototype, "sciScore", void 0);
|
|
45
|
-
__decorate([
|
|
46
|
-
(0, class_transformer_1.Expose)(),
|
|
47
|
-
(0, class_validator_1.IsOptional)(),
|
|
48
|
-
(0, class_validator_1.IsEnum)(ClientLevelEnum_1.ClientLevelEnum),
|
|
49
|
-
__metadata("design:type", String)
|
|
50
|
-
], UpsertLoanBorrowerRequest.prototype, "clientLevel", void 0);
|
|
51
|
-
__decorate([
|
|
52
|
-
(0, class_transformer_1.Expose)(),
|
|
53
|
-
(0, class_validator_1.IsOptional)(),
|
|
54
|
-
(0, class_validator_1.IsInt)(),
|
|
55
|
-
__metadata("design:type", Number)
|
|
56
|
-
], UpsertLoanBorrowerRequest.prototype, "bureauScore", void 0);
|
|
57
37
|
__decorate([
|
|
58
38
|
(0, class_transformer_1.Expose)(),
|
|
59
39
|
(0, class_validator_1.IsOptional)(),
|
|
@@ -6,7 +6,7 @@ import { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
|
|
|
6
6
|
export interface LoanBorrowerResponse {
|
|
7
7
|
borrowerId: string;
|
|
8
8
|
retailCustomerId: string;
|
|
9
|
-
|
|
9
|
+
directoryId: string;
|
|
10
10
|
sciScore?: number;
|
|
11
11
|
clientLevel?: ClientLevelEnum;
|
|
12
12
|
bureauScore?: number;
|
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Expose } from 'class-transformer';
|
|
2
|
+
import { IsEnum, IsOptional } from 'class-validator';
|
|
3
|
+
import { KycSubCheckStatusEnum } from '../enums/KycSubCheckStatusEnum';
|
|
4
|
+
import { KycWatchlistStatusEnum } from '../enums/KycWatchlistStatusEnum';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Los 8 sub-pasos del KYC de Metamap, descompuestos — el resultado de CADA estación, no el
|
|
8
|
+
* veredicto global. Viaja dentro de `KycVerificationChangedV1.subChecks`.
|
|
9
|
+
*
|
|
10
|
+
* **Por qué existe:** hoy el KYC llega como un solo bombillo (VERIFIED/REJECTED). Pero no todo
|
|
11
|
+
* fallo es igual: un facematch fallido es fraude, un hit de watchlist es "que lo mire cumplimiento",
|
|
12
|
+
* una mala foto es un reintento. Descomponerlo deja que SureKeep aplique una política por sub-paso.
|
|
13
|
+
*
|
|
14
|
+
* **El webhook los produce como TRADUCTOR, no como juez:** deriva cada uno de la presencia de
|
|
15
|
+
* `error` en el `step_completed` de Metamap. NO decide qué significa el fallo para la venta —
|
|
16
|
+
* esa política vive del lado de SureKeep (consolidación / oficial de cumplimiento).
|
|
17
|
+
*
|
|
18
|
+
* **Todos opcionales:** un flujo de Metamap puede no correr todas las estaciones. Un campo ausente
|
|
19
|
+
* significa "esa estación no corrió en este flujo", distinto de un `FAIL`.
|
|
20
|
+
*
|
|
21
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
22
|
+
*/
|
|
23
|
+
export class KycSubChecks {
|
|
24
|
+
/** ¿Se leyó bien el documento? Mala foto → FAIL (reintento). */
|
|
25
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
26
|
+
documentReading?: KycSubCheckStatusEnum;
|
|
27
|
+
|
|
28
|
+
/** ¿El documento es una plantilla válida (una INE de verdad)? */
|
|
29
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
30
|
+
templateMatching?: KycSubCheckStatusEnum;
|
|
31
|
+
|
|
32
|
+
/** ¿El documento fue alterado/photoshopeado? FAIL = detectó alteración. */
|
|
33
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
34
|
+
alterationDetection?: KycSubCheckStatusEnum;
|
|
35
|
+
|
|
36
|
+
/** ¿La cara de la selfie coincide con la del documento? FAIL = no coincide (suplantación). */
|
|
37
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
38
|
+
facematch?: KycSubCheckStatusEnum;
|
|
39
|
+
|
|
40
|
+
/** ¿Es una persona viva frente a la cámara y no una foto de una foto? FAIL = no vivo. */
|
|
41
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
42
|
+
liveness?: KycSubCheckStatusEnum;
|
|
43
|
+
|
|
44
|
+
/** ¿Tiene 18 o más? FAIL = menor de edad. */
|
|
45
|
+
@Expose() @IsOptional() @IsEnum(KycSubCheckStatusEnum)
|
|
46
|
+
ageCheck?: KycSubCheckStatusEnum;
|
|
47
|
+
|
|
48
|
+
/** ¿Apareció en una watchlist? HIT = apareció → oficial de cumplimiento (NO es rechazo). */
|
|
49
|
+
@Expose() @IsOptional() @IsEnum(KycWatchlistStatusEnum)
|
|
50
|
+
watchlists?: KycWatchlistStatusEnum;
|
|
51
|
+
|
|
52
|
+
/** ¿Apareció en una lista premium (PEP/sanciones)? HIT → oficial de cumplimiento. */
|
|
53
|
+
@Expose() @IsOptional() @IsEnum(KycWatchlistStatusEnum)
|
|
54
|
+
premiumAmlWatchlists?: KycWatchlistStatusEnum;
|
|
55
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resultado de un sub-paso BINARIO del KYC (los que pasan o fallan sin matices).
|
|
3
|
+
*
|
|
4
|
+
* El webhook lo deriva de la presencia/ausencia de `error` en el `step_completed` de Metamap:
|
|
5
|
+
* sin error → `PASS`, con error → `FAIL`. No hay tri-estado en estos.
|
|
6
|
+
*
|
|
7
|
+
* Aplica a: document-reading, template-matching, alteration-detection, facematch, liveness, age-check.
|
|
8
|
+
* (Las listas de watchlist usan `KycWatchlistStatusEnum` — un hit NO es un fallo.)
|
|
9
|
+
*
|
|
10
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
11
|
+
*/
|
|
12
|
+
export enum KycSubCheckStatusEnum {
|
|
13
|
+
PASS = 'PASS',
|
|
14
|
+
FAIL = 'FAIL',
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resultado de un sub-paso de LISTA del KYC (watchlists, premium-aml-watchlists).
|
|
3
|
+
*
|
|
4
|
+
* Deliberadamente NO reusa `KycSubCheckStatusEnum`: un `HIT` en una lista **no es un fallo**.
|
|
5
|
+
* Es un "que lo mire un humano" — el cliente aparece en una lista y un oficial de cumplimiento (D21)
|
|
6
|
+
* decide, en vez de rechazar automáticamente. Ese matiz es justo lo que el vocabulario binario
|
|
7
|
+
* pasado por alto perdía: si `HIT` fuera `FAIL`, la venta se bloquearía sola sin revisión.
|
|
8
|
+
*
|
|
9
|
+
* `CLEAR` = no apareció en ninguna lista. `HIT` = apareció, requiere revisión de cumplimiento.
|
|
10
|
+
*
|
|
11
|
+
* SureKeep Fase 2 — descomposición del KYC en sub-pasos.
|
|
12
|
+
*/
|
|
13
|
+
export enum KycWatchlistStatusEnum {
|
|
14
|
+
CLEAR = 'CLEAR',
|
|
15
|
+
HIT = 'HIT',
|
|
16
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { Expose } from 'class-transformer';
|
|
2
|
-
import { IsEnum, IsISO8601, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
|
1
|
+
import { Expose, Type } from 'class-transformer';
|
|
2
|
+
import { IsEnum, IsISO8601, IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
|
|
3
3
|
import { IdentificationDocumentStatus } from '../../identity/enums/IdentificationDocumentStatus';
|
|
4
4
|
import { KycVerificationStatusEnum } from '../enums/KycVerificationStatusEnum';
|
|
5
|
+
import { KycSubChecks } from '../dtos/KycSubChecks';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
|
-
* Cambio terminal de una verificación KYC, tal como
|
|
8
|
-
* `
|
|
8
|
+
* Cambio terminal de una verificación KYC, tal como lo publica `kyc-metamap-webhook` directo en
|
|
9
|
+
* `RetailKycInboundQueue` (el webhook manda un `SendMessage` cuando la verificación pasa a COMPLETED).
|
|
9
10
|
*
|
|
10
11
|
* NO lleva `tenantId`: el de la tabla es un valor hardcodeado que no discrimina silo.
|
|
11
12
|
* La pertenencia se resuelve en el consumer con el gate de `WizardSession`.
|
|
@@ -48,4 +49,15 @@ export class KycVerificationChangedV1 {
|
|
|
48
49
|
*/
|
|
49
50
|
@Expose() @IsString() @IsISO8601()
|
|
50
51
|
updateDate!: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Los 8 sub-pasos descompuestos (SureKeep F2). OPCIONAL y aditivo: un mensaje viejo sin
|
|
55
|
+
* `subChecks` sigue validando, y un consumidor que aún no aplica política los ignora sin romperse.
|
|
56
|
+
*
|
|
57
|
+
* El webhook los produce como traductor (error del `step_completed` → PASS/FAIL, o CLEAR/HIT
|
|
58
|
+
* para las listas). La POLÍTICA de qué hacer con cada uno (facematch FAIL → rechazo, watchlist
|
|
59
|
+
* HIT → oficial de cumplimiento, mala foto → reintento) vive del lado de SureKeep, NO aquí.
|
|
60
|
+
*/
|
|
61
|
+
@Expose() @IsOptional() @ValidateNested() @Type(() => KycSubChecks)
|
|
62
|
+
subChecks?: KycSubChecks;
|
|
51
63
|
}
|
package/src/kyc/index.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
// Enums (el consolidado reusa RetailKycStatusEnum del dominio retailCustomer — DEC-KYC-014;
|
|
2
2
|
// `verificationResult` reusa IdentificationDocumentStatus de `identity` — DEC-KYC-016)
|
|
3
3
|
export * from './enums/KycVerificationStatusEnum';
|
|
4
|
+
export * from './enums/KycSubCheckStatusEnum';
|
|
5
|
+
export * from './enums/KycWatchlistStatusEnum';
|
|
6
|
+
|
|
7
|
+
// Sub-pasos descompuestos (SureKeep F2)
|
|
8
|
+
export * from './dtos/KycSubChecks';
|
|
4
9
|
|
|
5
10
|
// Response DTOs
|
|
6
11
|
export * from './dtos/responses/KycPersonData';
|
|
@@ -28,11 +28,13 @@ export class LoanBorrower {
|
|
|
28
28
|
@IsString()
|
|
29
29
|
retailCustomerId!: string;
|
|
30
30
|
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* ANCLA canónica del acreditado: el directoryId de Fiado (identidad universal — L-hydrate,
|
|
33
|
+
* decisión 2026-07-22). `retailCustomerId` queda solo como referencia del tenant.
|
|
34
|
+
*/
|
|
32
35
|
@Expose()
|
|
33
|
-
@IsOptional()
|
|
34
36
|
@IsString()
|
|
35
|
-
|
|
37
|
+
directoryId!: string;
|
|
36
38
|
|
|
37
39
|
/** SCI vigente 0-100 (M7). Ausente hasta la primera evaluación. */
|
|
38
40
|
@Expose()
|
|
@@ -24,8 +24,8 @@ export class SignLoanCreditRequest {
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* SOLO en el inicio de firma (tiempo 1) con el OTP REAL de messages-business: el directoryId
|
|
27
|
-
* Fiado del cliente (lo aporta el WIZARD — dueño del dato; fallback: el
|
|
28
|
-
*
|
|
27
|
+
* Fiado del cliente (lo aporta el WIZARD — dueño del dato; fallback: el directoryId
|
|
28
|
+
* (ancla) del borrower). El OTP se genera/verifica keyeado a este id (D5).
|
|
29
29
|
*/
|
|
30
30
|
@Expose()
|
|
31
31
|
@IsOptional()
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import { Expose, Type } from 'class-transformer';
|
|
2
|
-
import {
|
|
3
|
-
IsEnum,
|
|
4
|
-
IsInt,
|
|
5
|
-
IsNotEmpty,
|
|
6
|
-
IsOptional,
|
|
7
|
-
IsString,
|
|
8
|
-
Max,
|
|
9
|
-
Min,
|
|
10
|
-
ValidateNested,
|
|
11
|
-
} from 'class-validator';
|
|
12
|
-
import { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
|
|
2
|
+
import { IsNotEmpty, IsOptional, IsString, ValidateNested } from 'class-validator';
|
|
13
3
|
import { LoanBeneficiary } from '../LoanBeneficiary';
|
|
14
4
|
|
|
15
5
|
/**
|
|
16
|
-
* Body de POST /
|
|
17
|
-
*
|
|
18
|
-
*
|
|
6
|
+
* Body de `POST /private/borrowers` (loan-credit-business) — ALTA ON-DEMAND del acreditado
|
|
7
|
+
* (paso 04 del wizard, al elegir SureKeep como forma de pago — decisión 2026-07-22, L-hydrate).
|
|
8
|
+
*
|
|
9
|
+
* El wizard solo IDENTIFICA al cliente: el motor hace un pull síncrono a `retail-customer`
|
|
10
|
+
* (`GET /private/customers/:id`), valida `kycStatus=VERIFIED` + identidad Fiado presente, y
|
|
11
|
+
* persiste el acreditado con ancla `directoryId`. La PII del pull es TRANSITORIA (no se guarda).
|
|
12
|
+
*
|
|
13
|
+
* Idempotente: si el acreditado ya existe, se devuelve/completa (una persona = una ficha).
|
|
14
|
+
* Errores: `KYC_NOT_VERIFIED` · `IDENTITY_MISSING` · `BORROWER_SOURCE_NOT_FOUND` ·
|
|
15
|
+
* `RETAIL_PULL_FAILED` (422/502 — ver openapi del motor).
|
|
19
16
|
*/
|
|
20
17
|
export class UpsertLoanBorrowerRequest {
|
|
21
18
|
@Expose()
|
|
@@ -23,29 +20,7 @@ export class UpsertLoanBorrowerRequest {
|
|
|
23
20
|
@IsNotEmpty()
|
|
24
21
|
retailCustomerId!: string;
|
|
25
22
|
|
|
26
|
-
/**
|
|
27
|
-
@Expose()
|
|
28
|
-
@IsOptional()
|
|
29
|
-
@IsString()
|
|
30
|
-
fiadoDirectoryId?: string;
|
|
31
|
-
|
|
32
|
-
@Expose()
|
|
33
|
-
@IsOptional()
|
|
34
|
-
@IsInt()
|
|
35
|
-
@Min(0)
|
|
36
|
-
@Max(100)
|
|
37
|
-
sciScore?: number;
|
|
38
|
-
|
|
39
|
-
@Expose()
|
|
40
|
-
@IsOptional()
|
|
41
|
-
@IsEnum(ClientLevelEnum)
|
|
42
|
-
clientLevel?: ClientLevelEnum;
|
|
43
|
-
|
|
44
|
-
@Expose()
|
|
45
|
-
@IsOptional()
|
|
46
|
-
@IsInt()
|
|
47
|
-
bureauScore?: number;
|
|
48
|
-
|
|
23
|
+
/** Beneficiario / a quién avisar (opcional — el wizard lo captura en su paso propio). */
|
|
49
24
|
@Expose()
|
|
50
25
|
@IsOptional()
|
|
51
26
|
@ValidateNested()
|
|
@@ -7,7 +7,7 @@ import { ClientLevelEnum } from '../../../loanScoring/enums/ClientLevelEnum';
|
|
|
7
7
|
export interface LoanBorrowerResponse {
|
|
8
8
|
borrowerId: string;
|
|
9
9
|
retailCustomerId: string;
|
|
10
|
-
|
|
10
|
+
directoryId: string;
|
|
11
11
|
sciScore?: number;
|
|
12
12
|
clientLevel?: ClientLevelEnum;
|
|
13
13
|
bureauScore?: number;
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare enum BenefitFlowEnum {
|
|
2
|
-
TOPUPS = "TOPUPS",
|
|
3
|
-
BILL_PAYMENT = "BILL_PAYMENT",
|
|
4
|
-
CREDIT = "CREDIT",
|
|
5
|
-
INSURANCE = "INSURANCE",
|
|
6
|
-
DONATION = "DONATION",
|
|
7
|
-
PHARMACY = "PHARMACY",
|
|
8
|
-
REMITTANCE = "REMITTANCE",
|
|
9
|
-
/** Fondeo de wallet PCF con efectivo via provider externo (Equality/Passport, OpenPay, …) — spec 13. */
|
|
10
|
-
WALLET_FUNDING = "WALLET_FUNDING"
|
|
11
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.BenefitFlowEnum = void 0;
|
|
4
|
-
var BenefitFlowEnum;
|
|
5
|
-
(function (BenefitFlowEnum) {
|
|
6
|
-
BenefitFlowEnum["TOPUPS"] = "TOPUPS";
|
|
7
|
-
BenefitFlowEnum["BILL_PAYMENT"] = "BILL_PAYMENT";
|
|
8
|
-
BenefitFlowEnum["CREDIT"] = "CREDIT";
|
|
9
|
-
BenefitFlowEnum["INSURANCE"] = "INSURANCE";
|
|
10
|
-
BenefitFlowEnum["DONATION"] = "DONATION";
|
|
11
|
-
BenefitFlowEnum["PHARMACY"] = "PHARMACY";
|
|
12
|
-
BenefitFlowEnum["REMITTANCE"] = "REMITTANCE";
|
|
13
|
-
/** Fondeo de wallet PCF con efectivo via provider externo (Equality/Passport, OpenPay, …) — spec 13. */
|
|
14
|
-
BenefitFlowEnum["WALLET_FUNDING"] = "WALLET_FUNDING";
|
|
15
|
-
})(BenefitFlowEnum || (exports.BenefitFlowEnum = BenefitFlowEnum = {}));
|
|
@@ -1,31 +0,0 @@
|
|
|
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.CancelFundingReferenceRequest = void 0;
|
|
13
|
-
const class_validator_1 = require("class-validator");
|
|
14
|
-
class CancelFundingReferenceRequest {
|
|
15
|
-
}
|
|
16
|
-
exports.CancelFundingReferenceRequest = CancelFundingReferenceRequest;
|
|
17
|
-
__decorate([
|
|
18
|
-
(0, class_validator_1.IsString)(),
|
|
19
|
-
(0, class_validator_1.MaxLength)(64),
|
|
20
|
-
__metadata("design:type", String)
|
|
21
|
-
], CancelFundingReferenceRequest.prototype, "reference", void 0);
|
|
22
|
-
__decorate([
|
|
23
|
-
(0, class_validator_1.IsString)(),
|
|
24
|
-
(0, class_validator_1.MaxLength)(64),
|
|
25
|
-
__metadata("design:type", String)
|
|
26
|
-
], CancelFundingReferenceRequest.prototype, "directoryId", void 0);
|
|
27
|
-
__decorate([
|
|
28
|
-
(0, class_validator_1.IsString)(),
|
|
29
|
-
(0, class_validator_1.MaxLength)(64),
|
|
30
|
-
__metadata("design:type", String)
|
|
31
|
-
], CancelFundingReferenceRequest.prototype, "idempotencyKey", void 0);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { BenefitPaymentStatusEnum } from "../../benefitCenter/enums/BenefitPaymentStatusEnum";
|
|
2
|
-
import { WalletFundingErrorCodeEnum } from "../enums/WalletFundingErrorCodeEnum";
|
|
3
|
-
export declare class CancelFundingReferenceResponse {
|
|
4
|
-
reference: string;
|
|
5
|
-
status: BenefitPaymentStatusEnum;
|
|
6
|
-
errorCode?: WalletFundingErrorCodeEnum;
|
|
7
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Request del cancel via Centro de Beneficios (spec 13 v2.0).
|
|
3
|
-
* `reference` viaja en el path, `directoryId` se resuelve del JWT.
|
|
4
|
-
* `providerModuleName` permite al marketplace rutear al publisher correcto
|
|
5
|
-
* sin tener que persistir el mapping (el wallet-app sabe el moduleName
|
|
6
|
-
* porque vino en la respuesta del authorize).
|
|
7
|
-
*/
|
|
8
|
-
export declare class CancelFundingRequest {
|
|
9
|
-
idempotencyKey: string;
|
|
10
|
-
providerModuleName: string;
|
|
11
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
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.CancelFundingRequest = void 0;
|
|
13
|
-
const class_validator_1 = require("class-validator");
|
|
14
|
-
/**
|
|
15
|
-
* Request del cancel via Centro de Beneficios (spec 13 v2.0).
|
|
16
|
-
* `reference` viaja en el path, `directoryId` se resuelve del JWT.
|
|
17
|
-
* `providerModuleName` permite al marketplace rutear al publisher correcto
|
|
18
|
-
* sin tener que persistir el mapping (el wallet-app sabe el moduleName
|
|
19
|
-
* porque vino en la respuesta del authorize).
|
|
20
|
-
*/
|
|
21
|
-
class CancelFundingRequest {
|
|
22
|
-
}
|
|
23
|
-
exports.CancelFundingRequest = CancelFundingRequest;
|
|
24
|
-
__decorate([
|
|
25
|
-
(0, class_validator_1.IsString)(),
|
|
26
|
-
(0, class_validator_1.MaxLength)(64),
|
|
27
|
-
__metadata("design:type", String)
|
|
28
|
-
], CancelFundingRequest.prototype, "idempotencyKey", void 0);
|
|
29
|
-
__decorate([
|
|
30
|
-
(0, class_validator_1.IsString)(),
|
|
31
|
-
(0, class_validator_1.MaxLength)(128),
|
|
32
|
-
__metadata("design:type", String)
|
|
33
|
-
], CancelFundingRequest.prototype, "providerModuleName", void 0);
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { BenefitPaymentStatusEnum } from "../../benefitCenter/enums/BenefitPaymentStatusEnum";
|
|
2
|
-
import { WalletFundingErrorCodeEnum } from "../enums/WalletFundingErrorCodeEnum";
|
|
3
|
-
/**
|
|
4
|
-
* Response del cancel via Centro de Beneficios (spec 13 v2.0).
|
|
5
|
-
* `status` reusa `BenefitPaymentStatusEnum` (APPROVED = cancel aceptado;
|
|
6
|
-
* REJECTED = no se pudo) para consistencia con `CancelFundingReferenceResponse`
|
|
7
|
-
* (marketplace ↔ connector). Idempotente: re-cancelar devuelve APPROVED.
|
|
8
|
-
*/
|
|
9
|
-
export declare class CancelFundingResponse {
|
|
10
|
-
reference: string;
|
|
11
|
-
status: BenefitPaymentStatusEnum;
|
|
12
|
-
errorCode?: WalletFundingErrorCodeEnum;
|
|
13
|
-
message?: string;
|
|
14
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CancelFundingResponse = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Response del cancel via Centro de Beneficios (spec 13 v2.0).
|
|
6
|
-
* `status` reusa `BenefitPaymentStatusEnum` (APPROVED = cancel aceptado;
|
|
7
|
-
* REJECTED = no se pudo) para consistencia con `CancelFundingReferenceResponse`
|
|
8
|
-
* (marketplace ↔ connector). Idempotente: re-cancelar devuelve APPROVED.
|
|
9
|
-
*/
|
|
10
|
-
class CancelFundingResponse {
|
|
11
|
-
}
|
|
12
|
-
exports.CancelFundingResponse = CancelFundingResponse;
|
|
@@ -1,21 +0,0 @@
|
|
|
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.CancelWalletFundingRequest = void 0;
|
|
13
|
-
const class_validator_1 = require("class-validator");
|
|
14
|
-
class CancelWalletFundingRequest {
|
|
15
|
-
}
|
|
16
|
-
exports.CancelWalletFundingRequest = CancelWalletFundingRequest;
|
|
17
|
-
__decorate([
|
|
18
|
-
(0, class_validator_1.IsString)(),
|
|
19
|
-
(0, class_validator_1.MaxLength)(64),
|
|
20
|
-
__metadata("design:type", String)
|
|
21
|
-
], CancelWalletFundingRequest.prototype, "idempotencyKey", void 0);
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import { BenefitPaymentStatusEnum } from "../../benefitCenter/enums/BenefitPaymentStatusEnum";
|
|
2
|
-
import { WalletFundingErrorCodeEnum } from "../enums/WalletFundingErrorCodeEnum";
|
|
3
|
-
export declare class CancelWalletFundingResponse {
|
|
4
|
-
status: BenefitPaymentStatusEnum;
|
|
5
|
-
errorCode?: WalletFundingErrorCodeEnum;
|
|
6
|
-
reference?: string;
|
|
7
|
-
}
|