@fiado/api-invoker 4.65.0 → 4.67.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/bin/index.d.ts +1 -0
- package/bin/index.js +1 -0
- package/bin/loanOfferings/api/LoanOfferingsBusinessApi.d.ts +25 -0
- package/bin/loanOfferings/api/LoanOfferingsBusinessApi.js +55 -0
- package/bin/loanOfferings/api/interfaces/ILoanOfferingsBusinessApi.d.ts +65 -0
- package/bin/loanOfferings/api/interfaces/ILoanOfferingsBusinessApi.js +1 -0
- package/bin/loanOfferings/index.d.ts +2 -0
- package/bin/loanOfferings/index.js +2 -0
- package/bin/platformRbac/api/PlatformRbacBusinessApi.d.ts +3 -1
- package/bin/platformRbac/api/PlatformRbacBusinessApi.js +8 -0
- package/bin/platformRbac/api/interfaces/IPlatformRbacBusinessApi.d.ts +13 -1
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/loanOfferings/api/LoanOfferingsBusinessApi.ts +62 -0
- package/src/loanOfferings/api/interfaces/ILoanOfferingsBusinessApi.ts +86 -0
- package/src/loanOfferings/index.ts +2 -0
- package/src/platformRbac/api/PlatformRbacBusinessApi.ts +22 -0
- package/src/platformRbac/api/interfaces/IPlatformRbacBusinessApi.ts +26 -0
package/bin/index.d.ts
CHANGED
|
@@ -78,6 +78,7 @@ export * from "./cognitoBackofficeConnector/index.js";
|
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
80
|
export * from "./loanConfig/index.js";
|
|
81
|
+
export * from "./loanOfferings/index.js";
|
|
81
82
|
export * from "./messages-business/index.js";
|
|
82
83
|
export * from "./totp-security/index.js";
|
|
83
84
|
export * from "./equality-connector/index.js";
|
package/bin/index.js
CHANGED
|
@@ -78,6 +78,7 @@ export * from "./cognitoBackofficeConnector/index.js";
|
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
80
|
export * from "./loanConfig/index.js";
|
|
81
|
+
export * from "./loanOfferings/index.js";
|
|
81
82
|
export * from "./messages-business/index.js";
|
|
82
83
|
export * from "./totp-security/index.js";
|
|
83
84
|
export * from "./equality-connector/index.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IHttpRequest } from "@fiado/http-client";
|
|
2
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
3
|
+
import { CreditPlanResponse, FinancierResponse, SimulateCreditPlanRequest, SimulationResultResponse } from "@fiado/type-kit/bin/loanOfferings/index.js";
|
|
4
|
+
import { ILoanOfferingsBusinessApi } from "./interfaces/ILoanOfferingsBusinessApi.js";
|
|
5
|
+
/**
|
|
6
|
+
* Publisher HTTP del lambda `loan-offerings-business` (componente 07 SureKeep Fase 1) para sus 4
|
|
7
|
+
* endpoints privados de lectura del catálogo. Contrato y semántica completos →
|
|
8
|
+
* `ILoanOfferingsBusinessApi` (tenantId obligatorio, `StandardResponse` → leer `result.data`).
|
|
9
|
+
*
|
|
10
|
+
* Env var requerida en el consumer: `LOAN_OFFERINGS_BUSINESS_URL`.
|
|
11
|
+
* El template.yml del consumer la setea con:
|
|
12
|
+
*
|
|
13
|
+
* LOAN_OFFERINGS_BUSINESS_URL: '{{resolve:ssm:loan-offerings-business}}'
|
|
14
|
+
*
|
|
15
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
16
|
+
*/
|
|
17
|
+
export default class LoanOfferingsBusinessApi implements ILoanOfferingsBusinessApi {
|
|
18
|
+
private httpRequest;
|
|
19
|
+
private readonly baseUrl;
|
|
20
|
+
constructor(httpRequest: IHttpRequest);
|
|
21
|
+
getCreditPlan(planId: string, tenantId: string): Promise<StandardResponse<CreditPlanResponse>>;
|
|
22
|
+
listActivePlansForRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<CreditPlanResponse[]>>;
|
|
23
|
+
listActiveFinanciers(tenantId: string): Promise<StandardResponse<FinancierResponse[]>>;
|
|
24
|
+
simulate(planId: string, input: SimulateCreditPlanRequest, tenantId: string): Promise<StandardResponse<SimulationResultResponse>>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
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;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from "inversify";
|
|
14
|
+
/**
|
|
15
|
+
* Publisher HTTP del lambda `loan-offerings-business` (componente 07 SureKeep Fase 1) para sus 4
|
|
16
|
+
* endpoints privados de lectura del catálogo. Contrato y semántica completos →
|
|
17
|
+
* `ILoanOfferingsBusinessApi` (tenantId obligatorio, `StandardResponse` → leer `result.data`).
|
|
18
|
+
*
|
|
19
|
+
* Env var requerida en el consumer: `LOAN_OFFERINGS_BUSINESS_URL`.
|
|
20
|
+
* El template.yml del consumer la setea con:
|
|
21
|
+
*
|
|
22
|
+
* LOAN_OFFERINGS_BUSINESS_URL: '{{resolve:ssm:loan-offerings-business}}'
|
|
23
|
+
*
|
|
24
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
25
|
+
*/
|
|
26
|
+
let LoanOfferingsBusinessApi = class LoanOfferingsBusinessApi {
|
|
27
|
+
httpRequest;
|
|
28
|
+
// El buildspec publica la URL en SSM con "/" final — se normaliza para no armar "//private".
|
|
29
|
+
baseUrl = (process.env.LOAN_OFFERINGS_BUSINESS_URL || "").replace(/\/+$/, "");
|
|
30
|
+
constructor(httpRequest) {
|
|
31
|
+
this.httpRequest = httpRequest;
|
|
32
|
+
}
|
|
33
|
+
async getCreditPlan(planId, tenantId) {
|
|
34
|
+
const url = `${this.baseUrl}/private/credit-plans/${encodeURIComponent(planId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
35
|
+
return await this.httpRequest.get(url);
|
|
36
|
+
}
|
|
37
|
+
async listActivePlansForRetailer(retailerId, tenantId) {
|
|
38
|
+
const url = `${this.baseUrl}/private/credit-plans/active-for-retailer/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
39
|
+
return await this.httpRequest.get(url);
|
|
40
|
+
}
|
|
41
|
+
async listActiveFinanciers(tenantId) {
|
|
42
|
+
const url = `${this.baseUrl}/private/financiers/active?tenantId=${encodeURIComponent(tenantId)}`;
|
|
43
|
+
return await this.httpRequest.get(url);
|
|
44
|
+
}
|
|
45
|
+
async simulate(planId, input, tenantId) {
|
|
46
|
+
const url = `${this.baseUrl}/private/credit-plans/${encodeURIComponent(planId)}/simulate?tenantId=${encodeURIComponent(tenantId)}`;
|
|
47
|
+
return await this.httpRequest.post(url, input);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
LoanOfferingsBusinessApi = __decorate([
|
|
51
|
+
injectable(),
|
|
52
|
+
__param(0, inject("IHttpRequest")),
|
|
53
|
+
__metadata("design:paramtypes", [Object])
|
|
54
|
+
], LoanOfferingsBusinessApi);
|
|
55
|
+
export default LoanOfferingsBusinessApi;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import { CreditPlanResponse, FinancierResponse, SimulateCreditPlanRequest, SimulationResultResponse } from "@fiado/type-kit/bin/loanOfferings/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Contrato del publisher HTTP del lambda `loan-offerings-business` (componente 07 SureKeep Fase 1)
|
|
5
|
+
* para sus 4 endpoints privados de LECTURA del catálogo SOFOM (service-to-service, VPC-only).
|
|
6
|
+
*
|
|
7
|
+
* loan-offerings es el catálogo comercial del SOFOM: planes de crédito + financieras + la relación
|
|
8
|
+
* M:N retailer↔plan + el simulador de cuota. Consumidores previstos:
|
|
9
|
+
* - wizard de originación (F2) → planes activos de un retailer · financieras activas
|
|
10
|
+
* - motor de crédito (F3) → leer un plan · simular la cuota (amortización + IVA + CAT)
|
|
11
|
+
*
|
|
12
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
* `tenantId` es OBLIGATORIO en los 4 métodos — no es un detalle de firma.
|
|
14
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
* Los privados NO llevan token de usuario (`Feature.ANONIMUS`; la protección es la red VPC), así que
|
|
16
|
+
* el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller declara el
|
|
17
|
+
* tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo. Sin `tenantId` →
|
|
18
|
+
* `400 UNKNOWN_TENANT` (fail-closed). Nunca hay default: caer a un tenant por default sería fail-OPEN
|
|
19
|
+
* y podría devolver el catálogo de otra SOFOM.
|
|
20
|
+
*
|
|
21
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
22
|
+
* ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
|
|
23
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
* `@fiado/http-client` devuelve el body pelado (`response.data` de axios); los publishers viejos que
|
|
25
|
+
* tipan `{ statusCode, body }` son ficción del tipo (ver `IRetailOrgBusinessApi`, donde está
|
|
26
|
+
* documentado el 500 que costó descubrirlo). Los publishers nuevos dicen la verdad.
|
|
27
|
+
*
|
|
28
|
+
* Errores: el lambda destino lanza `DomainError` tipado → el publisher RECHAZA (no devuelve null).
|
|
29
|
+
* Cada consumer mapea a su propio error de dominio (ver `fiado-api-invoker § 6`):
|
|
30
|
+
* `404 CREDIT_PLAN_NOT_FOUND` (planId inexistente)
|
|
31
|
+
* `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
|
|
32
|
+
*
|
|
33
|
+
* Env var requerida en el consumer: `LOAN_OFFERINGS_BUSINESS_URL`.
|
|
34
|
+
* El template.yml del consumer la setea con:
|
|
35
|
+
*
|
|
36
|
+
* LOAN_OFFERINGS_BUSINESS_URL: '{{resolve:ssm:loan-offerings-business}}'
|
|
37
|
+
*
|
|
38
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
39
|
+
*/
|
|
40
|
+
export interface ILoanOfferingsBusinessApi {
|
|
41
|
+
/**
|
|
42
|
+
* GET /private/credit-plans/{planId} — lee un plan completo por id (para el motor de crédito).
|
|
43
|
+
*
|
|
44
|
+
* @throws si el plan no existe (`404 CREDIT_PLAN_NOT_FOUND`).
|
|
45
|
+
*/
|
|
46
|
+
getCreditPlan(planId: string, tenantId: string): Promise<StandardResponse<CreditPlanResponse>>;
|
|
47
|
+
/**
|
|
48
|
+
* GET /private/credit-plans/active-for-retailer/{retailerId} — los planes ACTIVE que ese retailer
|
|
49
|
+
* puede ofrecer (para el wizard). Devuelve `[]` si el retailer no tiene planes activos (no 404).
|
|
50
|
+
*/
|
|
51
|
+
listActivePlansForRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<CreditPlanResponse[]>>;
|
|
52
|
+
/**
|
|
53
|
+
* GET /private/financiers/active — las financieras ACTIVE ordenadas por `displayOrder` (paso 4 del
|
|
54
|
+
* wizard). Devuelve `[]` si no hay financieras activas.
|
|
55
|
+
*/
|
|
56
|
+
listActiveFinanciers(tenantId: string): Promise<StandardResponse<FinancierResponse[]>>;
|
|
57
|
+
/**
|
|
58
|
+
* POST /private/credit-plans/{planId}/simulate — calcula la tabla de amortización (cuota semanal +
|
|
59
|
+
* IVA 16% + CAT) para un precio/enganche/plazo dados. Misma lógica que el simulador público.
|
|
60
|
+
*
|
|
61
|
+
* @throws si el plan no existe (`404 CREDIT_PLAN_NOT_FOUND`) o el input viola el plan
|
|
62
|
+
* (`400 INVALID_PLAN_PARAMETERS`, ej. plazo fuera de `termWeeksOptions`).
|
|
63
|
+
*/
|
|
64
|
+
simulate(planId: string, input: SimulateCreditPlanRequest, tenantId: string): Promise<StandardResponse<SimulationResultResponse>>;
|
|
65
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IHttpRequest } from "@fiado/http-client";
|
|
2
2
|
import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
|
|
3
|
-
import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
3
|
+
import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
4
4
|
import { IPlatformRbacBusinessApi } from "./interfaces/IPlatformRbacBusinessApi.js";
|
|
5
5
|
/**
|
|
6
6
|
* Publisher HTTP del lambda `platform-rbac-business` (componente 06 SureKeep Fase 0)
|
|
@@ -26,4 +26,6 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
|
|
|
26
26
|
effectivePermissions(cognitoSub: string, tenantId?: string): Promise<ApiGatewayResponse<EffectivePermissionsResponse>>;
|
|
27
27
|
getInjectableUserAttributes(cognitoSub: string, tenantId: string): Promise<ApiGatewayResponse<InjectableUserAttributesResponse>>;
|
|
28
28
|
resolvePermissions(input: ResolveInput): Promise<ApiGatewayResponse<ResolvedPermissions>>;
|
|
29
|
+
createLevelEntity(tenantId: string, level: PermissionScope, input: CreateLevelEntityRequest): Promise<ApiGatewayResponse<CreateLevelEntityResponse>>;
|
|
30
|
+
createTenantUser(tenantId: string, input: CreateTenantUserRequest): Promise<ApiGatewayResponse<CreateTenantUserResponse>>;
|
|
29
31
|
}
|
|
@@ -68,6 +68,14 @@ let PlatformRbacBusinessApi = class PlatformRbacBusinessApi {
|
|
|
68
68
|
const url = `${this.baseUrl}/internal/permissions/resolve`;
|
|
69
69
|
return await this.httpRequest.post(url, input);
|
|
70
70
|
}
|
|
71
|
+
async createLevelEntity(tenantId, level, input) {
|
|
72
|
+
const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/levels/${encodeURIComponent(level)}/entities`;
|
|
73
|
+
return await this.httpRequest.post(url, input);
|
|
74
|
+
}
|
|
75
|
+
async createTenantUser(tenantId, input) {
|
|
76
|
+
const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/users`;
|
|
77
|
+
return await this.httpRequest.post(url, input);
|
|
78
|
+
}
|
|
71
79
|
};
|
|
72
80
|
PlatformRbacBusinessApi = __decorate([
|
|
73
81
|
injectable(),
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
|
|
2
|
-
import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
2
|
+
import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
3
3
|
/**
|
|
4
4
|
* Contrato del publisher HTTP del lambda `platform-rbac-business` (componente 06 SureKeep Fase 0)
|
|
5
5
|
* para los 3 endpoints internos del Custom Auth Challenge flow (MFA).
|
|
@@ -63,4 +63,16 @@ export interface IPlatformRbacBusinessApi {
|
|
|
63
63
|
getInjectableUserAttributes(cognitoSub: string, tenantId: string): Promise<ApiGatewayResponse<InjectableUserAttributesResponse>>;
|
|
64
64
|
/** POST /internal/permissions/resolve — resuelve permisos scope-bound (set completo, paginación interna) para el RBAC enforcement del gateway-adapter. DEC-RBAC-064. */
|
|
65
65
|
resolvePermissions(input: ResolveInput): Promise<ApiGatewayResponse<ResolvedPermissions>>;
|
|
66
|
+
/**
|
|
67
|
+
* POST /internal/tenants/{tenantId}/levels/{level}/entities — crea una scope-entity genérica
|
|
68
|
+
* L1/L2/L3 en RBAC (endpoint privado, VPC/ANONIMUS). Espejo de jerarquía de SureKeep F1
|
|
69
|
+
* (retailer→L1, zona→L2, tienda→L3). BYOID + idempotente. `level` (LEVEL_1|2|3) va en el path.
|
|
70
|
+
*/
|
|
71
|
+
createLevelEntity(tenantId: string, level: PermissionScope, input: CreateLevelEntityRequest): Promise<ApiGatewayResponse<CreateLevelEntityResponse>>;
|
|
72
|
+
/**
|
|
73
|
+
* POST /internal/tenants/{tenantId}/users — provisiona un usuario del tenant (Cognito + SharedUser +
|
|
74
|
+
* RoleAssignment) en RBAC (endpoint privado, VPC/ANONIMUS). Alta orquestada de SureKeep F1: el usuario
|
|
75
|
+
* queda INVITED (mitiga orphan) y retail-org guarda el `cognitoSub` retornado. Idempotente por identidad Cognito.
|
|
76
|
+
*/
|
|
77
|
+
createTenantUser(tenantId: string, input: CreateTenantUserRequest): Promise<ApiGatewayResponse<CreateTenantUserResponse>>;
|
|
66
78
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiado/api-invoker",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.67.0",
|
|
4
4
|
"description": "Sirve como un puente entre diferentes funciones lambda, facilitando la comunicación entre ellas a través de invocaciones http",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@fiado/gateway-adapter": "^3.9.0",
|
|
35
35
|
"@fiado/http-client": "^2.0.1",
|
|
36
36
|
"@fiado/logger": "^1.1.3",
|
|
37
|
-
"@fiado/type-kit": "^3.
|
|
37
|
+
"@fiado/type-kit": "^3.193.0",
|
|
38
38
|
"dotenv": "^16.4.7"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -78,6 +78,7 @@ export * from "./cognitoBackofficeConnector/index.js";
|
|
|
78
78
|
export * from "./platformRbac/index.js";
|
|
79
79
|
export * from "./retailOrg/index.js";
|
|
80
80
|
export * from "./loanConfig/index.js";
|
|
81
|
+
export * from "./loanOfferings/index.js";
|
|
81
82
|
export * from "./messages-business/index.js";
|
|
82
83
|
export * from "./totp-security/index.js";
|
|
83
84
|
export * from "./equality-connector/index.js";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { inject, injectable } from "inversify";
|
|
2
|
+
import type { IHttpRequest } from "@fiado/http-client";
|
|
3
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
4
|
+
import {
|
|
5
|
+
CreditPlanResponse,
|
|
6
|
+
FinancierResponse,
|
|
7
|
+
SimulateCreditPlanRequest,
|
|
8
|
+
SimulationResultResponse,
|
|
9
|
+
} from "@fiado/type-kit/bin/loanOfferings/index.js";
|
|
10
|
+
import { ILoanOfferingsBusinessApi } from "./interfaces/ILoanOfferingsBusinessApi.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Publisher HTTP del lambda `loan-offerings-business` (componente 07 SureKeep Fase 1) para sus 4
|
|
14
|
+
* endpoints privados de lectura del catálogo. Contrato y semántica completos →
|
|
15
|
+
* `ILoanOfferingsBusinessApi` (tenantId obligatorio, `StandardResponse` → leer `result.data`).
|
|
16
|
+
*
|
|
17
|
+
* Env var requerida en el consumer: `LOAN_OFFERINGS_BUSINESS_URL`.
|
|
18
|
+
* El template.yml del consumer la setea con:
|
|
19
|
+
*
|
|
20
|
+
* LOAN_OFFERINGS_BUSINESS_URL: '{{resolve:ssm:loan-offerings-business}}'
|
|
21
|
+
*
|
|
22
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
23
|
+
*/
|
|
24
|
+
@injectable()
|
|
25
|
+
export default class LoanOfferingsBusinessApi implements ILoanOfferingsBusinessApi {
|
|
26
|
+
// El buildspec publica la URL en SSM con "/" final — se normaliza para no armar "//private".
|
|
27
|
+
private readonly baseUrl = (process.env.LOAN_OFFERINGS_BUSINESS_URL || "").replace(/\/+$/, "");
|
|
28
|
+
|
|
29
|
+
constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
|
|
30
|
+
|
|
31
|
+
async getCreditPlan(
|
|
32
|
+
planId: string,
|
|
33
|
+
tenantId: string,
|
|
34
|
+
): Promise<StandardResponse<CreditPlanResponse>> {
|
|
35
|
+
const url = `${this.baseUrl}/private/credit-plans/${encodeURIComponent(planId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
36
|
+
return await this.httpRequest.get(url);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async listActivePlansForRetailer(
|
|
40
|
+
retailerId: string,
|
|
41
|
+
tenantId: string,
|
|
42
|
+
): Promise<StandardResponse<CreditPlanResponse[]>> {
|
|
43
|
+
const url = `${this.baseUrl}/private/credit-plans/active-for-retailer/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
|
|
44
|
+
return await this.httpRequest.get(url);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async listActiveFinanciers(
|
|
48
|
+
tenantId: string,
|
|
49
|
+
): Promise<StandardResponse<FinancierResponse[]>> {
|
|
50
|
+
const url = `${this.baseUrl}/private/financiers/active?tenantId=${encodeURIComponent(tenantId)}`;
|
|
51
|
+
return await this.httpRequest.get(url);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async simulate(
|
|
55
|
+
planId: string,
|
|
56
|
+
input: SimulateCreditPlanRequest,
|
|
57
|
+
tenantId: string,
|
|
58
|
+
): Promise<StandardResponse<SimulationResultResponse>> {
|
|
59
|
+
const url = `${this.baseUrl}/private/credit-plans/${encodeURIComponent(planId)}/simulate?tenantId=${encodeURIComponent(tenantId)}`;
|
|
60
|
+
return await this.httpRequest.post(url, input);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { StandardResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import {
|
|
3
|
+
CreditPlanResponse,
|
|
4
|
+
FinancierResponse,
|
|
5
|
+
SimulateCreditPlanRequest,
|
|
6
|
+
SimulationResultResponse,
|
|
7
|
+
} from "@fiado/type-kit/bin/loanOfferings/index.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Contrato del publisher HTTP del lambda `loan-offerings-business` (componente 07 SureKeep Fase 1)
|
|
11
|
+
* para sus 4 endpoints privados de LECTURA del catálogo SOFOM (service-to-service, VPC-only).
|
|
12
|
+
*
|
|
13
|
+
* loan-offerings es el catálogo comercial del SOFOM: planes de crédito + financieras + la relación
|
|
14
|
+
* M:N retailer↔plan + el simulador de cuota. Consumidores previstos:
|
|
15
|
+
* - wizard de originación (F2) → planes activos de un retailer · financieras activas
|
|
16
|
+
* - motor de crédito (F3) → leer un plan · simular la cuota (amortización + IVA + CAT)
|
|
17
|
+
*
|
|
18
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
19
|
+
* `tenantId` es OBLIGATORIO en los 4 métodos — no es un detalle de firma.
|
|
20
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
21
|
+
* Los privados NO llevan token de usuario (`Feature.ANONIMUS`; la protección es la red VPC), así que
|
|
22
|
+
* el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller declara el
|
|
23
|
+
* tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo. Sin `tenantId` →
|
|
24
|
+
* `400 UNKNOWN_TENANT` (fail-closed). Nunca hay default: caer a un tenant por default sería fail-OPEN
|
|
25
|
+
* y podría devolver el catálogo de otra SOFOM.
|
|
26
|
+
*
|
|
27
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
28
|
+
* ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
|
|
29
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
30
|
+
* `@fiado/http-client` devuelve el body pelado (`response.data` de axios); los publishers viejos que
|
|
31
|
+
* tipan `{ statusCode, body }` son ficción del tipo (ver `IRetailOrgBusinessApi`, donde está
|
|
32
|
+
* documentado el 500 que costó descubrirlo). Los publishers nuevos dicen la verdad.
|
|
33
|
+
*
|
|
34
|
+
* Errores: el lambda destino lanza `DomainError` tipado → el publisher RECHAZA (no devuelve null).
|
|
35
|
+
* Cada consumer mapea a su propio error de dominio (ver `fiado-api-invoker § 6`):
|
|
36
|
+
* `404 CREDIT_PLAN_NOT_FOUND` (planId inexistente)
|
|
37
|
+
* `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
|
|
38
|
+
*
|
|
39
|
+
* Env var requerida en el consumer: `LOAN_OFFERINGS_BUSINESS_URL`.
|
|
40
|
+
* El template.yml del consumer la setea con:
|
|
41
|
+
*
|
|
42
|
+
* LOAN_OFFERINGS_BUSINESS_URL: '{{resolve:ssm:loan-offerings-business}}'
|
|
43
|
+
*
|
|
44
|
+
* Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
|
|
45
|
+
*/
|
|
46
|
+
export interface ILoanOfferingsBusinessApi {
|
|
47
|
+
/**
|
|
48
|
+
* GET /private/credit-plans/{planId} — lee un plan completo por id (para el motor de crédito).
|
|
49
|
+
*
|
|
50
|
+
* @throws si el plan no existe (`404 CREDIT_PLAN_NOT_FOUND`).
|
|
51
|
+
*/
|
|
52
|
+
getCreditPlan(
|
|
53
|
+
planId: string,
|
|
54
|
+
tenantId: string,
|
|
55
|
+
): Promise<StandardResponse<CreditPlanResponse>>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* GET /private/credit-plans/active-for-retailer/{retailerId} — los planes ACTIVE que ese retailer
|
|
59
|
+
* puede ofrecer (para el wizard). Devuelve `[]` si el retailer no tiene planes activos (no 404).
|
|
60
|
+
*/
|
|
61
|
+
listActivePlansForRetailer(
|
|
62
|
+
retailerId: string,
|
|
63
|
+
tenantId: string,
|
|
64
|
+
): Promise<StandardResponse<CreditPlanResponse[]>>;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* GET /private/financiers/active — las financieras ACTIVE ordenadas por `displayOrder` (paso 4 del
|
|
68
|
+
* wizard). Devuelve `[]` si no hay financieras activas.
|
|
69
|
+
*/
|
|
70
|
+
listActiveFinanciers(
|
|
71
|
+
tenantId: string,
|
|
72
|
+
): Promise<StandardResponse<FinancierResponse[]>>;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* POST /private/credit-plans/{planId}/simulate — calcula la tabla de amortización (cuota semanal +
|
|
76
|
+
* IVA 16% + CAT) para un precio/enganche/plazo dados. Misma lógica que el simulador público.
|
|
77
|
+
*
|
|
78
|
+
* @throws si el plan no existe (`404 CREDIT_PLAN_NOT_FOUND`) o el input viola el plan
|
|
79
|
+
* (`400 INVALID_PLAN_PARAMETERS`, ej. plazo fuera de `termWeeksOptions`).
|
|
80
|
+
*/
|
|
81
|
+
simulate(
|
|
82
|
+
planId: string,
|
|
83
|
+
input: SimulateCreditPlanRequest,
|
|
84
|
+
tenantId: string,
|
|
85
|
+
): Promise<StandardResponse<SimulationResultResponse>>;
|
|
86
|
+
}
|
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
AuthorizeResponse,
|
|
14
14
|
EffectivePermissionsResponse,
|
|
15
15
|
InjectableUserAttributesResponse,
|
|
16
|
+
PermissionScope,
|
|
17
|
+
CreateLevelEntityRequest,
|
|
18
|
+
CreateLevelEntityResponse,
|
|
19
|
+
CreateTenantUserRequest,
|
|
20
|
+
CreateTenantUserResponse,
|
|
16
21
|
} from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
17
22
|
import { IPlatformRbacBusinessApi } from "./interfaces/IPlatformRbacBusinessApi.js";
|
|
18
23
|
|
|
@@ -95,4 +100,21 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
|
|
|
95
100
|
const url = `${this.baseUrl}/internal/permissions/resolve`;
|
|
96
101
|
return await this.httpRequest.post(url, input);
|
|
97
102
|
}
|
|
103
|
+
|
|
104
|
+
async createLevelEntity(
|
|
105
|
+
tenantId: string,
|
|
106
|
+
level: PermissionScope,
|
|
107
|
+
input: CreateLevelEntityRequest,
|
|
108
|
+
): Promise<ApiGatewayResponse<CreateLevelEntityResponse>> {
|
|
109
|
+
const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/levels/${encodeURIComponent(level)}/entities`;
|
|
110
|
+
return await this.httpRequest.post(url, input);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async createTenantUser(
|
|
114
|
+
tenantId: string,
|
|
115
|
+
input: CreateTenantUserRequest,
|
|
116
|
+
): Promise<ApiGatewayResponse<CreateTenantUserResponse>> {
|
|
117
|
+
const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/users`;
|
|
118
|
+
return await this.httpRequest.post(url, input);
|
|
119
|
+
}
|
|
98
120
|
}
|
|
@@ -10,6 +10,11 @@ import {
|
|
|
10
10
|
AuthorizeResponse,
|
|
11
11
|
EffectivePermissionsResponse,
|
|
12
12
|
InjectableUserAttributesResponse,
|
|
13
|
+
PermissionScope,
|
|
14
|
+
CreateLevelEntityRequest,
|
|
15
|
+
CreateLevelEntityResponse,
|
|
16
|
+
CreateTenantUserRequest,
|
|
17
|
+
CreateTenantUserResponse,
|
|
13
18
|
} from "@fiado/type-kit/bin/platformRbac/index.js";
|
|
14
19
|
|
|
15
20
|
/**
|
|
@@ -95,4 +100,25 @@ export interface IPlatformRbacBusinessApi {
|
|
|
95
100
|
|
|
96
101
|
/** POST /internal/permissions/resolve — resuelve permisos scope-bound (set completo, paginación interna) para el RBAC enforcement del gateway-adapter. DEC-RBAC-064. */
|
|
97
102
|
resolvePermissions(input: ResolveInput): Promise<ApiGatewayResponse<ResolvedPermissions>>;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* POST /internal/tenants/{tenantId}/levels/{level}/entities — crea una scope-entity genérica
|
|
106
|
+
* L1/L2/L3 en RBAC (endpoint privado, VPC/ANONIMUS). Espejo de jerarquía de SureKeep F1
|
|
107
|
+
* (retailer→L1, zona→L2, tienda→L3). BYOID + idempotente. `level` (LEVEL_1|2|3) va en el path.
|
|
108
|
+
*/
|
|
109
|
+
createLevelEntity(
|
|
110
|
+
tenantId: string,
|
|
111
|
+
level: PermissionScope,
|
|
112
|
+
input: CreateLevelEntityRequest,
|
|
113
|
+
): Promise<ApiGatewayResponse<CreateLevelEntityResponse>>;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* POST /internal/tenants/{tenantId}/users — provisiona un usuario del tenant (Cognito + SharedUser +
|
|
117
|
+
* RoleAssignment) en RBAC (endpoint privado, VPC/ANONIMUS). Alta orquestada de SureKeep F1: el usuario
|
|
118
|
+
* queda INVITED (mitiga orphan) y retail-org guarda el `cognitoSub` retornado. Idempotente por identidad Cognito.
|
|
119
|
+
*/
|
|
120
|
+
createTenantUser(
|
|
121
|
+
tenantId: string,
|
|
122
|
+
input: CreateTenantUserRequest,
|
|
123
|
+
): Promise<ApiGatewayResponse<CreateTenantUserResponse>>;
|
|
98
124
|
}
|