@fiado/api-invoker 5.85.0 → 5.87.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.
@@ -2,6 +2,7 @@ import { IBenefitsMarketplaceApi } from "./interfaces/IBenefitsMarketplaceApi.js
2
2
  import { IHttpRequest } from "@fiado/http-client";
3
3
  import { BenefitPaymentRequest, BenefitPaymentResponse } from "@fiado/type-kit/bin/benefitCenter/index.js";
4
4
  import { ApiGatewayResponse } from "@fiado/gateway-adapter";
5
+ import { RemittanceOnboardingPrefillRequest, RemittanceOnboardingPrefillResponse } from "@fiado/type-kit/bin/remittance/index.js";
5
6
  import { BenefitLeafDisplayResponse } from "./dtos/BenefitLeafDisplayResponse.js";
6
7
  import { CreateFundingReferenceRequest, CreateFundingReferenceResponse, ListFundingReferencesResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
7
8
  export default class BenefitsMarketplaceApi implements IBenefitsMarketplaceApi {
@@ -13,4 +14,5 @@ export default class BenefitsMarketplaceApi implements IBenefitsMarketplaceApi {
13
14
  getLeafDisplay(benefitId: string, leafId: string): Promise<ApiGatewayResponse<BenefitLeafDisplayResponse>>;
14
15
  fundingCreate(moduleName: string, request: CreateFundingReferenceRequest): Promise<ApiGatewayResponse<CreateFundingReferenceResponse>>;
15
16
  fundingList(moduleName: string, directoryId: string, status?: string): Promise<ApiGatewayResponse<ListFundingReferencesResponse>>;
17
+ remittanceOnboardingPrefill(request: RemittanceOnboardingPrefillRequest): Promise<ApiGatewayResponse<RemittanceOnboardingPrefillResponse>>;
16
18
  }
@@ -40,6 +40,10 @@ let BenefitsMarketplaceApi = class BenefitsMarketplaceApi {
40
40
  const url = `${this.baseUrl}/funding/${encodeURIComponent(moduleName)}/references?${params.toString()}`;
41
41
  return await this.httpRequest.get(url);
42
42
  }
43
+ async remittanceOnboardingPrefill(request) {
44
+ const url = `${this.baseUrl}/remittance/onboarding/prefill`;
45
+ return await this.httpRequest.post(url, request);
46
+ }
43
47
  };
44
48
  BenefitsMarketplaceApi = __decorate([
45
49
  injectable(),
@@ -1,5 +1,6 @@
1
1
  import { BenefitPaymentRequest, BenefitPaymentResponse } from "@fiado/type-kit/bin/benefitCenter/index.js";
2
2
  import { ApiGatewayResponse } from "@fiado/gateway-adapter";
3
+ import { RemittanceOnboardingPrefillRequest, RemittanceOnboardingPrefillResponse } from "@fiado/type-kit/bin/remittance/index.js";
3
4
  import { BenefitLeafDisplayResponse } from "../dtos/BenefitLeafDisplayResponse.js";
4
5
  import { CreateFundingReferenceRequest, CreateFundingReferenceResponse, ListFundingReferencesResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
5
6
  /**
@@ -71,4 +72,11 @@ export interface IBenefitsMarketplaceApi {
71
72
  * Backend: GET /funding/{moduleName}/references?directoryId=&status=
72
73
  */
73
74
  fundingList(moduleName: string, directoryId: string, status?: string): Promise<ApiGatewayResponse<ListFundingReferencesResponse>>;
75
+ /**
76
+ * Composición del onboarding de remesas de un usuario SIN ejecutarla: lo que la app
77
+ * mandaría hoy (datos de Fiado) o el motivo de bloqueo + direcciones candidatas.
78
+ * Backend: POST /remittance/onboarding/prefill (privado VPC). Lo consume remittance-business
79
+ * para el reintento de registro desde el backoffice.
80
+ */
81
+ remittanceOnboardingPrefill(request: RemittanceOnboardingPrefillRequest): Promise<ApiGatewayResponse<RemittanceOnboardingPrefillResponse>>;
74
82
  }
@@ -1,6 +1,6 @@
1
1
  import type { IHttpRequest } from "@fiado/http-client";
2
- import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
3
- import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse, UserProfileResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
2
+ import { APIGatewayProxyResultBody, ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
3
+ import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse, UserProfileResponse, ListLevelEntitiesResponse, LevelEntityResponse, UpdateLevelEntityRequest, DeleteLevelEntityRequest, DeleteLevelEntityResponse, ListTenantUsersResponse, GetTenantUserResponse, TenantUserResponse, TenantUserAckResponse, UpdateTenantUserRequest, DeleteTenantUserRequest, DisableTenantUserRequest, EnableTenantUserRequest, ResetTenantUserPasswordRequest, ResetTenantUserPasswordResponse, ResetTenantUserMfaRequest, ListTenantRolesResponse, AssignTenantRoleRequest, AssignTenantRoleResponse, RevokeTenantRoleRequest, RevokeTenantRoleResponse } 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)
@@ -29,4 +29,51 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
29
29
  createLevelEntity(tenantId: string, level: PermissionScope, input: CreateLevelEntityRequest): Promise<ApiGatewayResponse<CreateLevelEntityResponse>>;
30
30
  createTenantUser(tenantId: string, input: CreateTenantUserRequest): Promise<ApiGatewayResponse<CreateTenantUserResponse>>;
31
31
  getUserProfile(cognitoSub: string, tenantId: string): Promise<ApiGatewayResponse<UserProfileResponse>>;
32
+ /** Ruta base de los grupos (entidades de nivel) de un tenant. */
33
+ private _levelEntitiesUrl;
34
+ /** Ruta base de los usuarios de un tenant. */
35
+ private _tenantUsersUrl;
36
+ private _deleteWithBody;
37
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities — lista los grupos de un nivel; `parentId` filtra por los hijos de un grupo. */
38
+ listLevelEntities(tenantId: string, level: PermissionScope, parentId?: string): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>>;
39
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
40
+ getLevelEntity(tenantId: string, level: PermissionScope, id: string): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
41
+ /** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo. */
42
+ updateLevelEntity(tenantId: string, level: PermissionScope, id: string, input: UpdateLevelEntityRequest): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
43
+ /** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
44
+ deleteLevelEntity(tenantId: string, level: PermissionScope, id: string, input: DeleteLevelEntityRequest): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>>;
45
+ /**
46
+ * GET /internal/tenants/{tenantId}/users — lista los usuarios del tenant.
47
+ * El filtro `email` es lo que permite adoptar una cuenta que ya existía.
48
+ */
49
+ listTenantUsers(tenantId: string, email?: string): Promise<APIGatewayProxyResultBody<ListTenantUsersResponse>>;
50
+ /**
51
+ * GET /internal/tenants/{tenantId}/users/{cognitoSub} — detalle de un usuario.
52
+ * De aquí sale el `assignmentId` que hace falta para revocar un rol.
53
+ */
54
+ getTenantUser(tenantId: string, cognitoSub: string): Promise<APIGatewayProxyResultBody<GetTenantUserResponse>>;
55
+ /** PUT /internal/tenants/{tenantId}/users/{cognitoSub} — renombra a un usuario. */
56
+ updateTenantUser(tenantId: string, cognitoSub: string, input: UpdateTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserResponse>>;
57
+ /** DELETE /internal/tenants/{tenantId}/users/{cognitoSub} — borra a un usuario. El `actedBy` viaja en el cuerpo. */
58
+ deleteTenantUser(tenantId: string, cognitoSub: string, input: DeleteTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
59
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/disable — suspende a un usuario. */
60
+ disableTenantUser(tenantId: string, cognitoSub: string, input: DisableTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
61
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/enable — reactiva a un usuario suspendido. */
62
+ enableTenantUser(tenantId: string, cognitoSub: string, input: EnableTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
63
+ /**
64
+ * POST /internal/tenants/{tenantId}/users/{cognitoSub}/password-reset — resetea la contraseña.
65
+ * Devuelve la contraseña temporal en claro; no se manda correo.
66
+ */
67
+ resetTenantUserPassword(tenantId: string, cognitoSub: string, input: ResetTenantUserPasswordRequest): Promise<APIGatewayProxyResultBody<ResetTenantUserPasswordResponse>>;
68
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/mfa-reset — resetea el MFA de un usuario. */
69
+ resetTenantUserMfa(tenantId: string, cognitoSub: string, input: ResetTenantUserMfaRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
70
+ /** GET /internal/tenants/{tenantId}/roles — catálogo de roles del tenant, para armar el selector de asignación. */
71
+ listTenantRoles(tenantId: string): Promise<APIGatewayProxyResultBody<ListTenantRolesResponse>>;
72
+ /** POST /internal/tenants/{tenantId}/role-assignments — asigna un rol a un usuario en un scope. */
73
+ assignTenantRole(tenantId: string, input: AssignTenantRoleRequest): Promise<APIGatewayProxyResultBody<AssignTenantRoleResponse>>;
74
+ /**
75
+ * POST /internal/tenants/{tenantId}/role-assignments/{assignmentId}/revoke — revoca una asignación.
76
+ * El `cognitoSub` va en el cuerpo porque es parte de la llave de la tabla de asignaciones.
77
+ */
78
+ revokeTenantRole(tenantId: string, assignmentId: string, input: RevokeTenantRoleRequest): Promise<APIGatewayProxyResultBody<RevokeTenantRoleResponse>>;
32
79
  }
@@ -80,6 +80,111 @@ let PlatformRbacBusinessApi = class PlatformRbacBusinessApi {
80
80
  const url = `${this.baseUrl}/internal/users/${encodeURIComponent(cognitoSub)}/profile?tenantId=${encodeURIComponent(tenantId)}`;
81
81
  return await this.httpRequest.get(url);
82
82
  }
83
+ // ── Administración de RBAC para el hub de agentes (grupos, usuarios y roles) ──
84
+ // Tipados `APIGatewayProxyResultBody<T>`, el shape REAL que devuelve @fiado/http-client:
85
+ // el body HTTP crudo `{ code, date, msg, data }`, con el payload en `.data` (TD-AI-003).
86
+ /** Ruta base de los grupos (entidades de nivel) de un tenant. */
87
+ _levelEntitiesUrl(tenantId, level) {
88
+ return `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/levels/${encodeURIComponent(level)}/entities`;
89
+ }
90
+ /** Ruta base de los usuarios de un tenant. */
91
+ _tenantUsersUrl(tenantId) {
92
+ return `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/users`;
93
+ }
94
+ // `IHttpRequest.delete` manda su segundo argumento como QUERY STRING, no como cuerpo: el cuerpo
95
+ // solo llega por `extraConfig` ({ data }). `actedBy` va ahí para no quedar en los logs de API Gateway.
96
+ async _deleteWithBody(url, body) {
97
+ return await this.httpRequest.delete(url, undefined, undefined, undefined, undefined, { data: body });
98
+ }
99
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities — lista los grupos de un nivel; `parentId` filtra por los hijos de un grupo. */
100
+ async listLevelEntities(tenantId, level, parentId) {
101
+ const base = this._levelEntitiesUrl(tenantId, level);
102
+ const url = parentId ? `${base}?parentId=${encodeURIComponent(parentId)}` : base;
103
+ return await this.httpRequest.get(url);
104
+ }
105
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
106
+ async getLevelEntity(tenantId, level, id) {
107
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
108
+ return await this.httpRequest.get(url);
109
+ }
110
+ /** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo. */
111
+ async updateLevelEntity(tenantId, level, id, input) {
112
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
113
+ return await this.httpRequest.put(url, input);
114
+ }
115
+ /** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
116
+ async deleteLevelEntity(tenantId, level, id, input) {
117
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
118
+ return await this._deleteWithBody(url, input);
119
+ }
120
+ /**
121
+ * GET /internal/tenants/{tenantId}/users — lista los usuarios del tenant.
122
+ * El filtro `email` es lo que permite adoptar una cuenta que ya existía.
123
+ */
124
+ async listTenantUsers(tenantId, email) {
125
+ const base = this._tenantUsersUrl(tenantId);
126
+ const url = email ? `${base}?email=${encodeURIComponent(email)}` : base;
127
+ return await this.httpRequest.get(url);
128
+ }
129
+ /**
130
+ * GET /internal/tenants/{tenantId}/users/{cognitoSub} — detalle de un usuario.
131
+ * De aquí sale el `assignmentId` que hace falta para revocar un rol.
132
+ */
133
+ async getTenantUser(tenantId, cognitoSub) {
134
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
135
+ return await this.httpRequest.get(url);
136
+ }
137
+ /** PUT /internal/tenants/{tenantId}/users/{cognitoSub} — renombra a un usuario. */
138
+ async updateTenantUser(tenantId, cognitoSub, input) {
139
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
140
+ return await this.httpRequest.put(url, input);
141
+ }
142
+ /** DELETE /internal/tenants/{tenantId}/users/{cognitoSub} — borra a un usuario. El `actedBy` viaja en el cuerpo. */
143
+ async deleteTenantUser(tenantId, cognitoSub, input) {
144
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
145
+ return await this._deleteWithBody(url, input);
146
+ }
147
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/disable — suspende a un usuario. */
148
+ async disableTenantUser(tenantId, cognitoSub, input) {
149
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/disable`;
150
+ return await this.httpRequest.post(url, input);
151
+ }
152
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/enable — reactiva a un usuario suspendido. */
153
+ async enableTenantUser(tenantId, cognitoSub, input) {
154
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/enable`;
155
+ return await this.httpRequest.post(url, input);
156
+ }
157
+ /**
158
+ * POST /internal/tenants/{tenantId}/users/{cognitoSub}/password-reset — resetea la contraseña.
159
+ * Devuelve la contraseña temporal en claro; no se manda correo.
160
+ */
161
+ async resetTenantUserPassword(tenantId, cognitoSub, input) {
162
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/password-reset`;
163
+ return await this.httpRequest.post(url, input);
164
+ }
165
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/mfa-reset — resetea el MFA de un usuario. */
166
+ async resetTenantUserMfa(tenantId, cognitoSub, input) {
167
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/mfa-reset`;
168
+ return await this.httpRequest.post(url, input);
169
+ }
170
+ /** GET /internal/tenants/{tenantId}/roles — catálogo de roles del tenant, para armar el selector de asignación. */
171
+ async listTenantRoles(tenantId) {
172
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/roles`;
173
+ return await this.httpRequest.get(url);
174
+ }
175
+ /** POST /internal/tenants/{tenantId}/role-assignments — asigna un rol a un usuario en un scope. */
176
+ async assignTenantRole(tenantId, input) {
177
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/role-assignments`;
178
+ return await this.httpRequest.post(url, input);
179
+ }
180
+ /**
181
+ * POST /internal/tenants/{tenantId}/role-assignments/{assignmentId}/revoke — revoca una asignación.
182
+ * El `cognitoSub` va en el cuerpo porque es parte de la llave de la tabla de asignaciones.
183
+ */
184
+ async revokeTenantRole(tenantId, assignmentId, input) {
185
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/role-assignments/${encodeURIComponent(assignmentId)}/revoke`;
186
+ return await this.httpRequest.post(url, input);
187
+ }
83
188
  };
84
189
  PlatformRbacBusinessApi = __decorate([
85
190
  injectable(),
@@ -1,5 +1,5 @@
1
- import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
2
- import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse, UserProfileResponse } from "@fiado/type-kit/bin/platformRbac/index.js";
1
+ import { APIGatewayProxyResultBody, ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
2
+ import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallengeRequest, PrepareChallengeResponse, VerifyChallengeRequest, VerifyChallengeResponse, AuthorizeRequest, AuthorizeResponse, EffectivePermissionsResponse, InjectableUserAttributesResponse, PermissionScope, CreateLevelEntityRequest, CreateLevelEntityResponse, CreateTenantUserRequest, CreateTenantUserResponse, UserProfileResponse, ListLevelEntitiesResponse, LevelEntityResponse, UpdateLevelEntityRequest, DeleteLevelEntityRequest, DeleteLevelEntityResponse, ListTenantUsersResponse, GetTenantUserResponse, TenantUserResponse, TenantUserAckResponse, UpdateTenantUserRequest, DeleteTenantUserRequest, DisableTenantUserRequest, EnableTenantUserRequest, ResetTenantUserPasswordRequest, ResetTenantUserPasswordResponse, ResetTenantUserMfaRequest, ListTenantRolesResponse, AssignTenantRoleRequest, AssignTenantRoleResponse, RevokeTenantRoleRequest, RevokeTenantRoleResponse } 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).
@@ -8,8 +8,8 @@ import { DefineNextChallengeRequest, DefineNextChallengeResponse, PrepareChallen
8
8
  * `defineAuthChallenge`, `createAuthChallenge` y `verifyAuthChallengeResponse`
9
9
  * configurados en cada User Pool aprovisionado por la saga `TenantOnboardingManager`.
10
10
  *
11
- * Patrón de retorno: `Promise<ApiGatewayResponse<T>>` sin unwrap (v4 canonical Fiado).
12
- * El consumer accede `result.body.data` para llegar al payload tipado.
11
+ * Devuelve el body HTTP crudo `{ code, date, msg, data }`, con el payload en `.data`: el tipo honesto es
12
+ * el de los métodos de administración. Los `ApiGatewayResponse<T>` mienten y quedan por TD-AI-003.
13
13
  *
14
14
  * Env var requerida en el consumer: `PLATFORM_RBAC_BUSINESS_URL`.
15
15
  * El template.yml del consumer la setea con:
@@ -77,4 +77,47 @@ export interface IPlatformRbacBusinessApi {
77
77
  createTenantUser(tenantId: string, input: CreateTenantUserRequest): Promise<ApiGatewayResponse<CreateTenantUserResponse>>;
78
78
  /** GET /internal/users/{cognitoSub}/profile?tenantId= — perfil básico del SharedUser (displayName, email, phone, status). */
79
79
  getUserProfile(cognitoSub: string, tenantId: string): Promise<ApiGatewayResponse<UserProfileResponse>>;
80
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities — lista los grupos de un nivel; `parentId` filtra por los hijos de un grupo. */
81
+ listLevelEntities(tenantId: string, level: PermissionScope, parentId?: string): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>>;
82
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
83
+ getLevelEntity(tenantId: string, level: PermissionScope, id: string): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
84
+ /** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo. */
85
+ updateLevelEntity(tenantId: string, level: PermissionScope, id: string, input: UpdateLevelEntityRequest): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
86
+ /** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
87
+ deleteLevelEntity(tenantId: string, level: PermissionScope, id: string, input: DeleteLevelEntityRequest): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>>;
88
+ /**
89
+ * GET /internal/tenants/{tenantId}/users — lista los usuarios del tenant.
90
+ * El filtro `email` es lo que permite adoptar una cuenta que ya existía: antes de crear un
91
+ * usuario se pregunta si ese correo ya tiene uno.
92
+ */
93
+ listTenantUsers(tenantId: string, email?: string): Promise<APIGatewayProxyResultBody<ListTenantUsersResponse>>;
94
+ /**
95
+ * GET /internal/tenants/{tenantId}/users/{cognitoSub} — detalle de un usuario.
96
+ * De aquí sale el `assignmentId` que hace falta para revocar un rol.
97
+ */
98
+ getTenantUser(tenantId: string, cognitoSub: string): Promise<APIGatewayProxyResultBody<GetTenantUserResponse>>;
99
+ /** PUT /internal/tenants/{tenantId}/users/{cognitoSub} — renombra a un usuario. */
100
+ updateTenantUser(tenantId: string, cognitoSub: string, input: UpdateTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserResponse>>;
101
+ /** DELETE /internal/tenants/{tenantId}/users/{cognitoSub} — borra a un usuario. El `actedBy` viaja en el cuerpo. */
102
+ deleteTenantUser(tenantId: string, cognitoSub: string, input: DeleteTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
103
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/disable — suspende a un usuario. */
104
+ disableTenantUser(tenantId: string, cognitoSub: string, input: DisableTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
105
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/enable — reactiva a un usuario suspendido. */
106
+ enableTenantUser(tenantId: string, cognitoSub: string, input: EnableTenantUserRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
107
+ /**
108
+ * POST /internal/tenants/{tenantId}/users/{cognitoSub}/password-reset — resetea la contraseña.
109
+ * Devuelve la contraseña temporal en claro; no se manda correo.
110
+ */
111
+ resetTenantUserPassword(tenantId: string, cognitoSub: string, input: ResetTenantUserPasswordRequest): Promise<APIGatewayProxyResultBody<ResetTenantUserPasswordResponse>>;
112
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/mfa-reset — resetea el MFA de un usuario. */
113
+ resetTenantUserMfa(tenantId: string, cognitoSub: string, input: ResetTenantUserMfaRequest): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
114
+ /** GET /internal/tenants/{tenantId}/roles — catálogo de roles del tenant, para armar el selector de asignación. */
115
+ listTenantRoles(tenantId: string): Promise<APIGatewayProxyResultBody<ListTenantRolesResponse>>;
116
+ /** POST /internal/tenants/{tenantId}/role-assignments — asigna un rol a un usuario en un scope. */
117
+ assignTenantRole(tenantId: string, input: AssignTenantRoleRequest): Promise<APIGatewayProxyResultBody<AssignTenantRoleResponse>>;
118
+ /**
119
+ * POST /internal/tenants/{tenantId}/role-assignments/{assignmentId}/revoke — revoca una asignación.
120
+ * El `cognitoSub` va en el cuerpo porque es parte de la llave de la tabla de asignaciones.
121
+ */
122
+ revokeTenantRole(tenantId: string, assignmentId: string, input: RevokeTenantRoleRequest): Promise<APIGatewayProxyResultBody<RevokeTenantRoleResponse>>;
80
123
  }
@@ -1,7 +1,7 @@
1
1
  import type { IHttpRequest } from "@fiado/http-client";
2
2
  import { ApiGatewayResponse } from "@fiado/gateway-adapter";
3
3
  import { ConnectorCatalogItem } from "@fiado/type-kit/bin/benefitCenter/index.js";
4
- import { CohortCountRequest, CohortCountResponse, CohortUserMatchRequest, CohortUserMatchResponse, PricingMetricsRequest, PricingMetricsResponse, PromotionReachRequest, PromotionReachResponse, SegmentMetricsRequest, SegmentMetricsResponse, WholesaleRateRequest, WholesaleRateResponse, KycUserDetail, KycUsersListResponse, KycOnboardingAttemptsResponse, RefreshUserProfileResponse, RegisterOnboardingBlockRequest, RegisterOnboardingBlockResponse, RemittanceAddBeneficiaryRequest, RemittanceBackofficeDashboardSummary, RemittanceBackofficeStats, RemittanceBackofficeStatsPeriod, RemittanceBackofficeCancelCloseRequest, RemittanceBackofficeCancelCloseResponse, RemittanceBackofficeTransaction, RemittanceBackofficeTxListResponse, RemittanceBackofficeUserDetail, RemittanceBackofficeUserListResponse, RemittanceBeneficiary, RemittanceCancelRequest, RemittanceCancelResponse, RemittanceHomeResponse, RemittanceListBeneficiariesResponse, RemittanceOnboardRequest, RemittanceOnboardResponse, RemittancePayRequest, RemittancePayResponse, RemittancePayerAdditionalFieldDto, RemittancePayerBranchDto, RemittancePayerDto, RemittanceQuoteRequest, RemittanceQuoteResponse, RemittanceSecurityQuestionsResponse, RemittanceSendPreviewRequest, RemittanceSendPreviewResponse, RemittanceSmsRequest, RemittanceStateDto, RemittanceTransactionDetail, RemittanceTransactionReceipt, RemittanceTransactionsListRequest, RemittanceTransactionsListResponse, RemittanceUpdateBeneficiaryRequest, RemittanceUserLimits, RemittanceUserLimitsBatchResponse, RemittanceCorridor, PricingScheduleResponse } from "@fiado/type-kit/bin/remittance/index.js";
4
+ import { CohortCountRequest, CohortCountResponse, CohortUserMatchRequest, CohortUserMatchResponse, PricingMetricsRequest, PricingMetricsResponse, PromotionReachRequest, PromotionReachResponse, SegmentMetricsRequest, SegmentMetricsResponse, WholesaleRateRequest, WholesaleRateResponse, KycUserDetail, KycUsersListResponse, KycOnboardingAttemptsResponse, RefreshUserProfileResponse, RegisterOnboardingBlockRequest, RegisterOnboardingBlockResponse, RemittanceAddBeneficiaryRequest, RemittanceBackofficeDashboardSummary, RemittanceBackofficeStats, RemittanceBackofficeStatsRangeRequest, RemittanceBackofficeStatsPeriod, RemittanceBackofficeCancelCloseRequest, RemittanceBackofficeCancelCloseResponse, RemittanceBackofficeTransaction, RemittanceBackofficeTxListResponse, RemittanceBackofficeUserDetail, RemittanceBackofficeUserListResponse, RemittanceBeneficiary, RemittanceCancelRequest, RemittanceCancelResponse, RemittanceHomeResponse, RemittanceListBeneficiariesResponse, RemittanceOnboardRequest, RemittanceOnboardResponse, RemittancePayRequest, RemittancePayResponse, RemittancePayerAdditionalFieldDto, RemittancePayerBranchDto, RemittancePayerDto, RemittanceQuoteRequest, RemittanceQuoteResponse, RemittanceSecurityQuestionsResponse, RemittanceSendPreviewRequest, RemittanceSendPreviewResponse, RemittanceSmsRequest, RemittanceStateDto, RemittanceTransactionDetail, RemittanceTransactionReceipt, RemittanceTransactionsListRequest, RemittanceTransactionsListResponse, RemittanceUpdateBeneficiaryRequest, RemittanceUserLimits, RemittanceUserLimitsBatchResponse, RemittanceCorridor, PricingScheduleResponse } from "@fiado/type-kit/bin/remittance/index.js";
5
5
  import { IUnitellerConnectorApi } from "./interfaces/IUnitellerConnectorApi.js";
6
6
  export default class UnitellerConnectorApi implements IUnitellerConnectorApi {
7
7
  private httpRequest;
@@ -27,9 +27,9 @@ export default class UnitellerConnectorApi implements IUnitellerConnectorApi {
27
27
  }): Promise<ApiGatewayResponse<RemittancePayerAdditionalFieldDto[]>>;
28
28
  listBeneficiaries(directoryId: string, includeDeactivated?: boolean): Promise<ApiGatewayResponse<RemittanceListBeneficiariesResponse>>;
29
29
  getBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
30
- addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
31
- updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
32
- deactivateBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<{
30
+ addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
31
+ updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
32
+ deactivateBeneficiary(directoryId: string, beneficiaryId: string, actor?: string): Promise<ApiGatewayResponse<{
33
33
  deactivated: boolean;
34
34
  beneficiaryId: string;
35
35
  }>>;
@@ -70,6 +70,7 @@ export default class UnitellerConnectorApi implements IUnitellerConnectorApi {
70
70
  backofficeSyncTransaction(txNumber: string): Promise<ApiGatewayResponse<RemittanceBackofficeTransaction>>;
71
71
  backofficeCloseCancellation(txNumber: string, request: RemittanceBackofficeCancelCloseRequest): Promise<ApiGatewayResponse<RemittanceBackofficeCancelCloseResponse>>;
72
72
  backofficeStats(period: RemittanceBackofficeStatsPeriod): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
73
+ backofficeStatsRange(request: RemittanceBackofficeStatsRangeRequest): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
73
74
  backofficeUserLimits(directoryId: string): Promise<ApiGatewayResponse<RemittanceUserLimits>>;
74
75
  backofficeUserLimitsBatch(directoryIds: string[]): Promise<ApiGatewayResponse<RemittanceUserLimitsBatchResponse>>;
75
76
  kycListUsers(filters?: {
@@ -65,17 +65,17 @@ let UnitellerConnectorApi = class UnitellerConnectorApi {
65
65
  const url = `${this.baseUrl}/beneficiaries/${encodeURIComponent(beneficiaryId)}`;
66
66
  return await this.httpRequest.post(url, { directoryId });
67
67
  }
68
- async addBeneficiary(directoryId, request) {
68
+ async addBeneficiary(directoryId, request, actor) {
69
69
  const url = `${this.baseUrl}/beneficiaries`;
70
- return await this.httpRequest.post(url, { directoryId, ...request });
70
+ return await this.httpRequest.post(url, { directoryId, ...request, ...(actor && { actor }) });
71
71
  }
72
- async updateBeneficiary(directoryId, beneficiaryId, request) {
72
+ async updateBeneficiary(directoryId, beneficiaryId, request, actor) {
73
73
  const url = `${this.baseUrl}/beneficiaries/${encodeURIComponent(beneficiaryId)}`;
74
- return await this.httpRequest.put(url, { directoryId, ...request });
74
+ return await this.httpRequest.put(url, { directoryId, ...request, ...(actor && { actor }) });
75
75
  }
76
- async deactivateBeneficiary(directoryId, beneficiaryId) {
76
+ async deactivateBeneficiary(directoryId, beneficiaryId, actor) {
77
77
  const url = `${this.baseUrl}/beneficiaries/${encodeURIComponent(beneficiaryId)}/deactivate`;
78
- return await this.httpRequest.post(url, { directoryId });
78
+ return await this.httpRequest.post(url, { directoryId, ...(actor && { actor }) });
79
79
  }
80
80
  async pricingSchedule(directoryId, corridor) {
81
81
  const url = `${this.baseUrl}/pricing/schedule`;
@@ -157,6 +157,14 @@ let UnitellerConnectorApi = class UnitellerConnectorApi {
157
157
  const url = `${this.baseUrl}/backoffice/stats`;
158
158
  return await this.httpRequest.get(url, { period });
159
159
  }
160
+ async backofficeStatsRange(request) {
161
+ const url = `${this.baseUrl}/backoffice/stats`;
162
+ return await this.httpRequest.get(url, {
163
+ from: request.from,
164
+ to: request.to,
165
+ ...(request.tzOffsetMinutes !== undefined && { tzOffsetMinutes: String(request.tzOffsetMinutes) }),
166
+ });
167
+ }
160
168
  async backofficeUserLimits(directoryId) {
161
169
  const url = `${this.baseUrl}/backoffice/users/${encodeURIComponent(directoryId)}/limits`;
162
170
  return await this.httpRequest.get(url);
@@ -1,6 +1,6 @@
1
1
  import { ApiGatewayResponse } from "@fiado/gateway-adapter";
2
2
  import { ConnectorCatalogItem } from "@fiado/type-kit/bin/benefitCenter/index.js";
3
- import { CohortCountRequest, CohortCountResponse, CohortUserMatchRequest, CohortUserMatchResponse, PricingMetricsRequest, PricingMetricsResponse, PromotionReachRequest, PromotionReachResponse, SegmentMetricsRequest, SegmentMetricsResponse, WholesaleRateRequest, WholesaleRateResponse, RemittanceCorridor, PricingScheduleResponse, KycUserDetail, KycUsersListResponse, KycOnboardingAttemptsResponse, RefreshUserProfileResponse, RegisterOnboardingBlockRequest, RegisterOnboardingBlockResponse, RemittanceAddBeneficiaryRequest, RemittanceBackofficeDashboardSummary, RemittanceBackofficeStats, RemittanceBackofficeStatsPeriod, RemittanceBackofficeCancelCloseRequest, RemittanceBackofficeCancelCloseResponse, RemittanceBackofficeTransaction, RemittanceBackofficeTxListResponse, RemittanceBackofficeUserDetail, RemittanceBackofficeUserListResponse, RemittanceBeneficiary, RemittanceCancelRequest, RemittanceCancelResponse, RemittanceHomeResponse, RemittanceListBeneficiariesResponse, RemittanceOnboardRequest, RemittanceOnboardResponse, RemittancePayRequest, RemittancePayResponse, RemittancePayerAdditionalFieldDto, RemittancePayerBranchDto, RemittancePayerDto, RemittanceQuoteRequest, RemittanceQuoteResponse, RemittanceSecurityQuestionsResponse, RemittanceSendPreviewRequest, RemittanceSendPreviewResponse, RemittanceSmsRequest, RemittanceStateDto, RemittanceTransactionDetail, RemittanceTransactionReceipt, RemittanceTransactionsListRequest, RemittanceTransactionsListResponse, RemittanceUpdateBeneficiaryRequest, RemittanceUserLimits, RemittanceUserLimitsBatchResponse } from "@fiado/type-kit/bin/remittance/index.js";
3
+ import { CohortCountRequest, CohortCountResponse, CohortUserMatchRequest, CohortUserMatchResponse, PricingMetricsRequest, PricingMetricsResponse, PromotionReachRequest, PromotionReachResponse, SegmentMetricsRequest, SegmentMetricsResponse, WholesaleRateRequest, WholesaleRateResponse, RemittanceCorridor, PricingScheduleResponse, KycUserDetail, KycUsersListResponse, KycOnboardingAttemptsResponse, RefreshUserProfileResponse, RegisterOnboardingBlockRequest, RegisterOnboardingBlockResponse, RemittanceAddBeneficiaryRequest, RemittanceBackofficeDashboardSummary, RemittanceBackofficeStats, RemittanceBackofficeStatsRangeRequest, RemittanceBackofficeStatsPeriod, RemittanceBackofficeCancelCloseRequest, RemittanceBackofficeCancelCloseResponse, RemittanceBackofficeTransaction, RemittanceBackofficeTxListResponse, RemittanceBackofficeUserDetail, RemittanceBackofficeUserListResponse, RemittanceBeneficiary, RemittanceCancelRequest, RemittanceCancelResponse, RemittanceHomeResponse, RemittanceListBeneficiariesResponse, RemittanceOnboardRequest, RemittanceOnboardResponse, RemittancePayRequest, RemittancePayResponse, RemittancePayerAdditionalFieldDto, RemittancePayerBranchDto, RemittancePayerDto, RemittanceQuoteRequest, RemittanceQuoteResponse, RemittanceSecurityQuestionsResponse, RemittanceSendPreviewRequest, RemittanceSendPreviewResponse, RemittanceSmsRequest, RemittanceStateDto, RemittanceTransactionDetail, RemittanceTransactionReceipt, RemittanceTransactionsListRequest, RemittanceTransactionsListResponse, RemittanceUpdateBeneficiaryRequest, RemittanceUserLimits, RemittanceUserLimitsBatchResponse } from "@fiado/type-kit/bin/remittance/index.js";
4
4
  export interface IUnitellerConnectorApi {
5
5
  /** Estado del módulo remesas para un directoryId. */
6
6
  getHome(directoryId: string): Promise<ApiGatewayResponse<RemittanceHomeResponse>>;
@@ -38,9 +38,10 @@ export interface IUnitellerConnectorApi {
38
38
  }): Promise<ApiGatewayResponse<RemittancePayerAdditionalFieldDto[]>>;
39
39
  listBeneficiaries(directoryId: string, includeDeactivated?: boolean): Promise<ApiGatewayResponse<RemittanceListBeneficiariesResponse>>;
40
40
  getBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
41
- addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
42
- updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
43
- deactivateBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<{
41
+ /** `actor` opcional ("BACKOFFICE:<email>") cuando la operación no la hace el usuario; queda en createdBy/updatedBy. */
42
+ addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
43
+ updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
44
+ deactivateBeneficiary(directoryId: string, beneficiaryId: string, actor?: string): Promise<ApiGatewayResponse<{
44
45
  deactivated: boolean;
45
46
  beneficiaryId: string;
46
47
  }>>;
@@ -122,6 +123,8 @@ export interface IUnitellerConnectorApi {
122
123
  /** Cierre manual de una cancelación: UPDATE a UniTeller + credit-back. */
123
124
  backofficeCloseCancellation(txNumber: string, request: RemittanceBackofficeCancelCloseRequest): Promise<ApiGatewayResponse<RemittanceBackofficeCancelCloseResponse>>;
124
125
  backofficeStats(period: RemittanceBackofficeStatsPeriod): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
126
+ /** Stats por rango explícito (from/to ISO) agrupando los días con el desfase del operador. GET /backoffice/stats. */
127
+ backofficeStatsRange(request: RemittanceBackofficeStatsRangeRequest): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
125
128
  /** Límites por usuario (Operación · read-only): ventanas (límite del provider + usage) + nivel + discrepancia. */
126
129
  backofficeUserLimits(directoryId: string): Promise<ApiGatewayResponse<RemittanceUserLimits>>;
127
130
  /** Batch de límites para la tabla de Límites (CSV de directoryIds). */
package/docs/TECH_DEBT.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  Registro vivo de deudas conscientes del repo. Cada entrada con ID estable `TD-AI-NNN` y los 4 campos canónicos (contexto / asunción / condición para cerrar / bloqueante).
4
4
 
5
- ## TD-AI-001 — 2026-05-29 — npm link @fiado/type-kit activo
5
+ ## TD-AI-001 — 2026-05-29 — CERRADA 2026-09-21 — npm link @fiado/type-kit activo
6
+
7
+ - **Cierre:** el symlink se quitó y se reinstaló `@fiado/type-kit@3.455.0` desde el registry. `tsc --noEmit` en cero y 331 tests en verde, así que el módulo `platformRbac` ya resuelve sin link. El detalle de abajo es histórico.
6
8
 
7
9
  - **Contexto:** `node_modules/@fiado/type-kit` es symlink local a `C:/Users/Fiado/Documents/Repos/fiado-type-kit/` (v3.43.1) — el publicado en CodeArtifact es v3.42.0 sin el módulo `platformRbac` que el Publisher `PlatformRbacBusinessApi` nuevo (`src/platformRbac/`) importa. El link se activó para iterar localmente sin publish prematuro del type-kit (decisión del user en el plan `2026-05-29-custom-auth-challenge-mfa.md`).
8
10
  - **Asunción / pendiente:** el `npm run build` y `tsc --noEmit` funcionan con el link, pero CI y cualquier `npm install` fresh van a resolver desde CodeArtifact (3.42.0) y fallar con `TS2307: Cannot find module '@fiado/type-kit/bin/platformRbac'` en los 2 archivos nuevos del Publisher.
@@ -21,3 +23,17 @@ Registro vivo de deudas conscientes del repo. Cada entrada con ID estable `TD-AI
21
23
  - **Asunción / pendiente:** se tiparon inline a propósito para no bloquear el cableado del wizard F2 en un bump de type-kit (regla de la sesión: NO tocar type-kit sin OK). Los shapes espejan fielmente el contrato del destino verificado en código.
22
24
  - **Condición para cerrar:** cuando `retail-catalog-business`/`retail-cards-business` publiquen esos DTOs en `@fiado/type-kit` (dominios `retailCatalog`/`retailCards`), reemplazar los inline por el import del type-kit y bumpear.
23
25
  - **Bloqueante:** NO — el contrato de red es correcto; es unificación de tipos con downstream.
26
+
27
+ ## TD-AI-003 — 2026-09-21 — el tipo de retorno de los publishers miente sobre el shape real
28
+
29
+ - **Contexto:** `@fiado/http-client` hace `return response.data` de axios, así que lo que llega en runtime es el body HTTP crudo del `ApiResponse` del lambda destino: `{ code, date, msg, data }`, con el payload en `.data`. Los 43 archivos de `src/` que declaran `Promise<ApiGatewayResponse<T>>` (`{ statusCode, body }`) declaran un shape que nunca existe. Ya costó un crash: leer `.body` en `ApiInvokerPermissionResolver` daba `undefined` y reventaba `enforceRbac`, y `retail-org-business` compensa con `response as unknown as Record<string, unknown>` + `(raw?.data ?? raw)` al consumir `createLevelEntity`.
30
+ - **Asunción / pendiente:** los 15 métodos de administración de RBAC (`listLevelEntities`..`revokeTenantRole`) ya se tipan `APIGatewayProxyResultBody<T>` de `@fiado/gateway-adapter`, que es el shape honesto — mismo precedente que `CollectorApi.getCollectorTransactionByIds`. Los métodos viejos NO se tocaron: corregirlos por abajo rompe la compensación de los consumidores vivos que ya leen `?? raw`.
31
+ - **Condición para cerrar:** migrar los 43 archivos a `APIGatewayProxyResultBody<T>` en un bump coordinado, quitando en el mismo movimiento los casts de compensación de cada consumer (arrancando por `retail-org-business`). No es de este ciclo.
32
+ - **Bloqueante:** NO — el contrato de red es correcto y el shape honesto ya es el de los métodos nuevos; es unificación de tipos.
33
+
34
+ ## TD-AI-004 — 2026-09-21 — CERRADA — npm link @fiado/type-kit (DTOs de administración de RBAC)
35
+
36
+ - **Contexto:** durante el desarrollo, `node_modules/@fiado/type-kit` fue symlink al repo local porque los 15 métodos de administración de RBAC importaban DTOs que la versión publicada todavía no tenía.
37
+ - **Cómo se cerró:** publicada `@fiado/type-kit@3.455.0`, se quitó el symlink y se reinstaló desde el registry. `tsc --noEmit` en cero y 331 tests en verde contra el árbol del registry.
38
+ - **Lo que el link tapaba, y conviene recordar:** `tsc` no limpia `bin/`, así que artefactos compilados de DTOs ya borrados seguían resolviendo a través del symlink. Un `npm link` puede hacer compilar contra tipos que ya no existen.
39
+ - **Trampa del teardown:** `npm unlink <pkg>` en npm 7+ es alias de `uninstall` y BORRA la dependencia de `package.json`. Hay que restaurarla antes del `npm install`, o el paquete se resuelve como transitiva en una versión vieja.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/api-invoker",
3
- "version": "5.85.0",
3
+ "version": "5.87.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.435.0",
37
+ "@fiado/type-kit": "^3.441.0",
38
38
  "dotenv": "^16.4.7"
39
39
  },
40
40
  "peerDependencies": {
@@ -3,6 +3,7 @@ import {inject, injectable} from "inversify";
3
3
  import {IHttpRequest} from "@fiado/http-client";
4
4
  import {BenefitPaymentRequest, BenefitPaymentResponse} from "@fiado/type-kit/bin/benefitCenter/index.js";
5
5
  import {ApiGatewayResponse} from "@fiado/gateway-adapter";
6
+ import {RemittanceOnboardingPrefillRequest, RemittanceOnboardingPrefillResponse} from "@fiado/type-kit/bin/remittance/index.js";
6
7
  import {BenefitLeafDisplayResponse} from "./dtos/BenefitLeafDisplayResponse.js";
7
8
  import {
8
9
  CreateFundingReferenceRequest,
@@ -56,4 +57,11 @@ export default class BenefitsMarketplaceApi implements IBenefitsMarketplaceApi {
56
57
  const url = `${this.baseUrl}/funding/${encodeURIComponent(moduleName)}/references?${params.toString()}`;
57
58
  return await this.httpRequest.get(url);
58
59
  }
60
+
61
+ async remittanceOnboardingPrefill(
62
+ request: RemittanceOnboardingPrefillRequest,
63
+ ): Promise<ApiGatewayResponse<RemittanceOnboardingPrefillResponse>> {
64
+ const url = `${this.baseUrl}/remittance/onboarding/prefill`;
65
+ return await this.httpRequest.post(url, request);
66
+ }
59
67
  }
@@ -1,5 +1,6 @@
1
1
  import {BenefitPaymentRequest, BenefitPaymentResponse} from "@fiado/type-kit/bin/benefitCenter/index.js";
2
2
  import {ApiGatewayResponse} from "@fiado/gateway-adapter";
3
+ import {RemittanceOnboardingPrefillRequest, RemittanceOnboardingPrefillResponse} from "@fiado/type-kit/bin/remittance/index.js";
3
4
  import {BenefitLeafDisplayResponse} from "../dtos/BenefitLeafDisplayResponse.js";
4
5
  import {
5
6
  CreateFundingReferenceRequest,
@@ -90,4 +91,14 @@ export interface IBenefitsMarketplaceApi {
90
91
  directoryId: string,
91
92
  status?: string,
92
93
  ): Promise<ApiGatewayResponse<ListFundingReferencesResponse>>;
94
+
95
+ /**
96
+ * Composición del onboarding de remesas de un usuario SIN ejecutarla: lo que la app
97
+ * mandaría hoy (datos de Fiado) o el motivo de bloqueo + direcciones candidatas.
98
+ * Backend: POST /remittance/onboarding/prefill (privado VPC). Lo consume remittance-business
99
+ * para el reintento de registro desde el backoffice.
100
+ */
101
+ remittanceOnboardingPrefill(
102
+ request: RemittanceOnboardingPrefillRequest,
103
+ ): Promise<ApiGatewayResponse<RemittanceOnboardingPrefillResponse>>;
93
104
  }
@@ -1,7 +1,12 @@
1
1
  import { inject, injectable } from "inversify";
2
2
  import type { IHttpRequest } from "@fiado/http-client";
3
- import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
4
- // TD-AI-001: import de @fiado/type-kit/bin/platformRbac requiere npm link a type-kit 3.43.1 hasta publish final. Ver docs/TECH_DEBT.md.
3
+ import {
4
+ APIGatewayProxyResultBody,
5
+ ApiGatewayResponse,
6
+ ResolvedPermissions,
7
+ ResolveInput,
8
+ } from "@fiado/gateway-adapter";
9
+ // TD-AI-003: el tipo de retorno de los métodos viejos no refleja el runtime. Ver docs/TECH_DEBT.md.
5
10
  import {
6
11
  DefineNextChallengeRequest,
7
12
  DefineNextChallengeResponse,
@@ -19,6 +24,27 @@ import {
19
24
  CreateTenantUserRequest,
20
25
  CreateTenantUserResponse,
21
26
  UserProfileResponse,
27
+ ListLevelEntitiesResponse,
28
+ LevelEntityResponse,
29
+ UpdateLevelEntityRequest,
30
+ DeleteLevelEntityRequest,
31
+ DeleteLevelEntityResponse,
32
+ ListTenantUsersResponse,
33
+ GetTenantUserResponse,
34
+ TenantUserResponse,
35
+ TenantUserAckResponse,
36
+ UpdateTenantUserRequest,
37
+ DeleteTenantUserRequest,
38
+ DisableTenantUserRequest,
39
+ EnableTenantUserRequest,
40
+ ResetTenantUserPasswordRequest,
41
+ ResetTenantUserPasswordResponse,
42
+ ResetTenantUserMfaRequest,
43
+ ListTenantRolesResponse,
44
+ AssignTenantRoleRequest,
45
+ AssignTenantRoleResponse,
46
+ RevokeTenantRoleRequest,
47
+ RevokeTenantRoleResponse,
22
48
  } from "@fiado/type-kit/bin/platformRbac/index.js";
23
49
  import { IPlatformRbacBusinessApi } from "./interfaces/IPlatformRbacBusinessApi.js";
24
50
 
@@ -126,4 +152,185 @@ export default class PlatformRbacBusinessApi implements IPlatformRbacBusinessApi
126
152
  const url = `${this.baseUrl}/internal/users/${encodeURIComponent(cognitoSub)}/profile?tenantId=${encodeURIComponent(tenantId)}`;
127
153
  return await this.httpRequest.get(url);
128
154
  }
155
+
156
+ // ── Administración de RBAC para el hub de agentes (grupos, usuarios y roles) ──
157
+ // Tipados `APIGatewayProxyResultBody<T>`, el shape REAL que devuelve @fiado/http-client:
158
+ // el body HTTP crudo `{ code, date, msg, data }`, con el payload en `.data` (TD-AI-003).
159
+
160
+ /** Ruta base de los grupos (entidades de nivel) de un tenant. */
161
+ private _levelEntitiesUrl(tenantId: string, level: PermissionScope): string {
162
+ return `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/levels/${encodeURIComponent(level)}/entities`;
163
+ }
164
+
165
+ /** Ruta base de los usuarios de un tenant. */
166
+ private _tenantUsersUrl(tenantId: string): string {
167
+ return `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/users`;
168
+ }
169
+
170
+ // `IHttpRequest.delete` manda su segundo argumento como QUERY STRING, no como cuerpo: el cuerpo
171
+ // solo llega por `extraConfig` ({ data }). `actedBy` va ahí para no quedar en los logs de API Gateway.
172
+ private async _deleteWithBody<T>(url: string, body: unknown): Promise<T> {
173
+ return await this.httpRequest.delete<T>(url, undefined, undefined, undefined, undefined, { data: body });
174
+ }
175
+
176
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities — lista los grupos de un nivel; `parentId` filtra por los hijos de un grupo. */
177
+ async listLevelEntities(
178
+ tenantId: string,
179
+ level: PermissionScope,
180
+ parentId?: string,
181
+ ): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>> {
182
+ const base = this._levelEntitiesUrl(tenantId, level);
183
+ const url = parentId ? `${base}?parentId=${encodeURIComponent(parentId)}` : base;
184
+ return await this.httpRequest.get(url);
185
+ }
186
+
187
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
188
+ async getLevelEntity(
189
+ tenantId: string,
190
+ level: PermissionScope,
191
+ id: string,
192
+ ): Promise<APIGatewayProxyResultBody<LevelEntityResponse>> {
193
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
194
+ return await this.httpRequest.get(url);
195
+ }
196
+
197
+ /** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo. */
198
+ async updateLevelEntity(
199
+ tenantId: string,
200
+ level: PermissionScope,
201
+ id: string,
202
+ input: UpdateLevelEntityRequest,
203
+ ): Promise<APIGatewayProxyResultBody<LevelEntityResponse>> {
204
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
205
+ return await this.httpRequest.put(url, input);
206
+ }
207
+
208
+ /** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
209
+ async deleteLevelEntity(
210
+ tenantId: string,
211
+ level: PermissionScope,
212
+ id: string,
213
+ input: DeleteLevelEntityRequest,
214
+ ): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>> {
215
+ const url = `${this._levelEntitiesUrl(tenantId, level)}/${encodeURIComponent(id)}`;
216
+ return await this._deleteWithBody(url, input);
217
+ }
218
+
219
+ /**
220
+ * GET /internal/tenants/{tenantId}/users — lista los usuarios del tenant.
221
+ * El filtro `email` es lo que permite adoptar una cuenta que ya existía.
222
+ */
223
+ async listTenantUsers(
224
+ tenantId: string,
225
+ email?: string,
226
+ ): Promise<APIGatewayProxyResultBody<ListTenantUsersResponse>> {
227
+ const base = this._tenantUsersUrl(tenantId);
228
+ const url = email ? `${base}?email=${encodeURIComponent(email)}` : base;
229
+ return await this.httpRequest.get(url);
230
+ }
231
+
232
+ /**
233
+ * GET /internal/tenants/{tenantId}/users/{cognitoSub} — detalle de un usuario.
234
+ * De aquí sale el `assignmentId` que hace falta para revocar un rol.
235
+ */
236
+ async getTenantUser(
237
+ tenantId: string,
238
+ cognitoSub: string,
239
+ ): Promise<APIGatewayProxyResultBody<GetTenantUserResponse>> {
240
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
241
+ return await this.httpRequest.get(url);
242
+ }
243
+
244
+ /** PUT /internal/tenants/{tenantId}/users/{cognitoSub} — renombra a un usuario. */
245
+ async updateTenantUser(
246
+ tenantId: string,
247
+ cognitoSub: string,
248
+ input: UpdateTenantUserRequest,
249
+ ): Promise<APIGatewayProxyResultBody<TenantUserResponse>> {
250
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
251
+ return await this.httpRequest.put(url, input);
252
+ }
253
+
254
+ /** DELETE /internal/tenants/{tenantId}/users/{cognitoSub} — borra a un usuario. El `actedBy` viaja en el cuerpo. */
255
+ async deleteTenantUser(
256
+ tenantId: string,
257
+ cognitoSub: string,
258
+ input: DeleteTenantUserRequest,
259
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>> {
260
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}`;
261
+ return await this._deleteWithBody(url, input);
262
+ }
263
+
264
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/disable — suspende a un usuario. */
265
+ async disableTenantUser(
266
+ tenantId: string,
267
+ cognitoSub: string,
268
+ input: DisableTenantUserRequest,
269
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>> {
270
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/disable`;
271
+ return await this.httpRequest.post(url, input);
272
+ }
273
+
274
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/enable — reactiva a un usuario suspendido. */
275
+ async enableTenantUser(
276
+ tenantId: string,
277
+ cognitoSub: string,
278
+ input: EnableTenantUserRequest,
279
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>> {
280
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/enable`;
281
+ return await this.httpRequest.post(url, input);
282
+ }
283
+
284
+ /**
285
+ * POST /internal/tenants/{tenantId}/users/{cognitoSub}/password-reset — resetea la contraseña.
286
+ * Devuelve la contraseña temporal en claro; no se manda correo.
287
+ */
288
+ async resetTenantUserPassword(
289
+ tenantId: string,
290
+ cognitoSub: string,
291
+ input: ResetTenantUserPasswordRequest,
292
+ ): Promise<APIGatewayProxyResultBody<ResetTenantUserPasswordResponse>> {
293
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/password-reset`;
294
+ return await this.httpRequest.post(url, input);
295
+ }
296
+
297
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/mfa-reset — resetea el MFA de un usuario. */
298
+ async resetTenantUserMfa(
299
+ tenantId: string,
300
+ cognitoSub: string,
301
+ input: ResetTenantUserMfaRequest,
302
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>> {
303
+ const url = `${this._tenantUsersUrl(tenantId)}/${encodeURIComponent(cognitoSub)}/mfa-reset`;
304
+ return await this.httpRequest.post(url, input);
305
+ }
306
+
307
+ /** GET /internal/tenants/{tenantId}/roles — catálogo de roles del tenant, para armar el selector de asignación. */
308
+ async listTenantRoles(
309
+ tenantId: string,
310
+ ): Promise<APIGatewayProxyResultBody<ListTenantRolesResponse>> {
311
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/roles`;
312
+ return await this.httpRequest.get(url);
313
+ }
314
+
315
+ /** POST /internal/tenants/{tenantId}/role-assignments — asigna un rol a un usuario en un scope. */
316
+ async assignTenantRole(
317
+ tenantId: string,
318
+ input: AssignTenantRoleRequest,
319
+ ): Promise<APIGatewayProxyResultBody<AssignTenantRoleResponse>> {
320
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/role-assignments`;
321
+ return await this.httpRequest.post(url, input);
322
+ }
323
+
324
+ /**
325
+ * POST /internal/tenants/{tenantId}/role-assignments/{assignmentId}/revoke — revoca una asignación.
326
+ * El `cognitoSub` va en el cuerpo porque es parte de la llave de la tabla de asignaciones.
327
+ */
328
+ async revokeTenantRole(
329
+ tenantId: string,
330
+ assignmentId: string,
331
+ input: RevokeTenantRoleRequest,
332
+ ): Promise<APIGatewayProxyResultBody<RevokeTenantRoleResponse>> {
333
+ const url = `${this.baseUrl}/internal/tenants/${encodeURIComponent(tenantId)}/role-assignments/${encodeURIComponent(assignmentId)}/revoke`;
334
+ return await this.httpRequest.post(url, input);
335
+ }
129
336
  }
@@ -1,4 +1,9 @@
1
- import { ApiGatewayResponse, ResolvedPermissions, ResolveInput } from "@fiado/gateway-adapter";
1
+ import {
2
+ APIGatewayProxyResultBody,
3
+ ApiGatewayResponse,
4
+ ResolvedPermissions,
5
+ ResolveInput,
6
+ } from "@fiado/gateway-adapter";
2
7
  import {
3
8
  DefineNextChallengeRequest,
4
9
  DefineNextChallengeResponse,
@@ -16,6 +21,27 @@ import {
16
21
  CreateTenantUserRequest,
17
22
  CreateTenantUserResponse,
18
23
  UserProfileResponse,
24
+ ListLevelEntitiesResponse,
25
+ LevelEntityResponse,
26
+ UpdateLevelEntityRequest,
27
+ DeleteLevelEntityRequest,
28
+ DeleteLevelEntityResponse,
29
+ ListTenantUsersResponse,
30
+ GetTenantUserResponse,
31
+ TenantUserResponse,
32
+ TenantUserAckResponse,
33
+ UpdateTenantUserRequest,
34
+ DeleteTenantUserRequest,
35
+ DisableTenantUserRequest,
36
+ EnableTenantUserRequest,
37
+ ResetTenantUserPasswordRequest,
38
+ ResetTenantUserPasswordResponse,
39
+ ResetTenantUserMfaRequest,
40
+ ListTenantRolesResponse,
41
+ AssignTenantRoleRequest,
42
+ AssignTenantRoleResponse,
43
+ RevokeTenantRoleRequest,
44
+ RevokeTenantRoleResponse,
19
45
  } from "@fiado/type-kit/bin/platformRbac/index.js";
20
46
 
21
47
  /**
@@ -26,8 +52,8 @@ import {
26
52
  * `defineAuthChallenge`, `createAuthChallenge` y `verifyAuthChallengeResponse`
27
53
  * configurados en cada User Pool aprovisionado por la saga `TenantOnboardingManager`.
28
54
  *
29
- * Patrón de retorno: `Promise<ApiGatewayResponse<T>>` sin unwrap (v4 canonical Fiado).
30
- * El consumer accede `result.body.data` para llegar al payload tipado.
55
+ * Devuelve el body HTTP crudo `{ code, date, msg, data }`, con el payload en `.data`: el tipo honesto es
56
+ * el de los métodos de administración. Los `ApiGatewayResponse<T>` mienten y quedan por TD-AI-003.
31
57
  *
32
58
  * Env var requerida en el consumer: `PLATFORM_RBAC_BUSINESS_URL`.
33
59
  * El template.yml del consumer la setea con:
@@ -128,4 +154,123 @@ export interface IPlatformRbacBusinessApi {
128
154
  cognitoSub: string,
129
155
  tenantId: string,
130
156
  ): Promise<ApiGatewayResponse<UserProfileResponse>>;
157
+
158
+ // ── Administración de RBAC para el hub de agentes (grupos, usuarios y roles) ──
159
+ // Estos métodos declaran el shape REAL de retorno: `APIGatewayProxyResultBody<T>` = el body
160
+ // HTTP crudo del ApiResponse de rbac, con el payload en `.data` (TD-AI-003).
161
+
162
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities — lista los grupos de un nivel; `parentId` filtra por los hijos de un grupo. */
163
+ listLevelEntities(
164
+ tenantId: string,
165
+ level: PermissionScope,
166
+ parentId?: string,
167
+ ): Promise<APIGatewayProxyResultBody<ListLevelEntitiesResponse>>;
168
+
169
+ /** GET /internal/tenants/{tenantId}/levels/{level}/entities/{id} — detalle de un grupo. */
170
+ getLevelEntity(
171
+ tenantId: string,
172
+ level: PermissionScope,
173
+ id: string,
174
+ ): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
175
+
176
+ /** PUT /internal/tenants/{tenantId}/levels/{level}/entities/{id} — renombra un grupo. */
177
+ updateLevelEntity(
178
+ tenantId: string,
179
+ level: PermissionScope,
180
+ id: string,
181
+ input: UpdateLevelEntityRequest,
182
+ ): Promise<APIGatewayProxyResultBody<LevelEntityResponse>>;
183
+
184
+ /** DELETE /internal/tenants/{tenantId}/levels/{level}/entities/{id} — borra un grupo. El `actedBy` viaja en el cuerpo. */
185
+ deleteLevelEntity(
186
+ tenantId: string,
187
+ level: PermissionScope,
188
+ id: string,
189
+ input: DeleteLevelEntityRequest,
190
+ ): Promise<APIGatewayProxyResultBody<DeleteLevelEntityResponse>>;
191
+
192
+ /**
193
+ * GET /internal/tenants/{tenantId}/users — lista los usuarios del tenant.
194
+ * El filtro `email` es lo que permite adoptar una cuenta que ya existía: antes de crear un
195
+ * usuario se pregunta si ese correo ya tiene uno.
196
+ */
197
+ listTenantUsers(
198
+ tenantId: string,
199
+ email?: string,
200
+ ): Promise<APIGatewayProxyResultBody<ListTenantUsersResponse>>;
201
+
202
+ /**
203
+ * GET /internal/tenants/{tenantId}/users/{cognitoSub} — detalle de un usuario.
204
+ * De aquí sale el `assignmentId` que hace falta para revocar un rol.
205
+ */
206
+ getTenantUser(
207
+ tenantId: string,
208
+ cognitoSub: string,
209
+ ): Promise<APIGatewayProxyResultBody<GetTenantUserResponse>>;
210
+
211
+ /** PUT /internal/tenants/{tenantId}/users/{cognitoSub} — renombra a un usuario. */
212
+ updateTenantUser(
213
+ tenantId: string,
214
+ cognitoSub: string,
215
+ input: UpdateTenantUserRequest,
216
+ ): Promise<APIGatewayProxyResultBody<TenantUserResponse>>;
217
+
218
+ /** DELETE /internal/tenants/{tenantId}/users/{cognitoSub} — borra a un usuario. El `actedBy` viaja en el cuerpo. */
219
+ deleteTenantUser(
220
+ tenantId: string,
221
+ cognitoSub: string,
222
+ input: DeleteTenantUserRequest,
223
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
224
+
225
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/disable — suspende a un usuario. */
226
+ disableTenantUser(
227
+ tenantId: string,
228
+ cognitoSub: string,
229
+ input: DisableTenantUserRequest,
230
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
231
+
232
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/enable — reactiva a un usuario suspendido. */
233
+ enableTenantUser(
234
+ tenantId: string,
235
+ cognitoSub: string,
236
+ input: EnableTenantUserRequest,
237
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
238
+
239
+ /**
240
+ * POST /internal/tenants/{tenantId}/users/{cognitoSub}/password-reset — resetea la contraseña.
241
+ * Devuelve la contraseña temporal en claro; no se manda correo.
242
+ */
243
+ resetTenantUserPassword(
244
+ tenantId: string,
245
+ cognitoSub: string,
246
+ input: ResetTenantUserPasswordRequest,
247
+ ): Promise<APIGatewayProxyResultBody<ResetTenantUserPasswordResponse>>;
248
+
249
+ /** POST /internal/tenants/{tenantId}/users/{cognitoSub}/mfa-reset — resetea el MFA de un usuario. */
250
+ resetTenantUserMfa(
251
+ tenantId: string,
252
+ cognitoSub: string,
253
+ input: ResetTenantUserMfaRequest,
254
+ ): Promise<APIGatewayProxyResultBody<TenantUserAckResponse>>;
255
+
256
+ /** GET /internal/tenants/{tenantId}/roles — catálogo de roles del tenant, para armar el selector de asignación. */
257
+ listTenantRoles(
258
+ tenantId: string,
259
+ ): Promise<APIGatewayProxyResultBody<ListTenantRolesResponse>>;
260
+
261
+ /** POST /internal/tenants/{tenantId}/role-assignments — asigna un rol a un usuario en un scope. */
262
+ assignTenantRole(
263
+ tenantId: string,
264
+ input: AssignTenantRoleRequest,
265
+ ): Promise<APIGatewayProxyResultBody<AssignTenantRoleResponse>>;
266
+
267
+ /**
268
+ * POST /internal/tenants/{tenantId}/role-assignments/{assignmentId}/revoke — revoca una asignación.
269
+ * El `cognitoSub` va en el cuerpo porque es parte de la llave de la tabla de asignaciones.
270
+ */
271
+ revokeTenantRole(
272
+ tenantId: string,
273
+ assignmentId: string,
274
+ input: RevokeTenantRoleRequest,
275
+ ): Promise<APIGatewayProxyResultBody<RevokeTenantRoleResponse>>;
131
276
  }
@@ -24,6 +24,7 @@ import {
24
24
  RemittanceAddBeneficiaryRequest,
25
25
  RemittanceBackofficeDashboardSummary,
26
26
  RemittanceBackofficeStats,
27
+ RemittanceBackofficeStatsRangeRequest,
27
28
  RemittanceBackofficeStatsPeriod,
28
29
  RemittanceBackofficeCancelCloseRequest,
29
30
  RemittanceBackofficeCancelCloseResponse,
@@ -126,19 +127,19 @@ export default class UnitellerConnectorApi implements IUnitellerConnectorApi {
126
127
  return await this.httpRequest.post(url, { directoryId });
127
128
  }
128
129
 
129
- async addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>> {
130
+ async addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>> {
130
131
  const url = `${this.baseUrl}/beneficiaries`;
131
- return await this.httpRequest.post(url, { directoryId, ...request });
132
+ return await this.httpRequest.post(url, { directoryId, ...request, ...(actor && { actor }) });
132
133
  }
133
134
 
134
- async updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>> {
135
+ async updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>> {
135
136
  const url = `${this.baseUrl}/beneficiaries/${encodeURIComponent(beneficiaryId)}`;
136
- return await this.httpRequest.put(url, { directoryId, ...request });
137
+ return await this.httpRequest.put(url, { directoryId, ...request, ...(actor && { actor }) });
137
138
  }
138
139
 
139
- async deactivateBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<{ deactivated: boolean; beneficiaryId: string }>> {
140
+ async deactivateBeneficiary(directoryId: string, beneficiaryId: string, actor?: string): Promise<ApiGatewayResponse<{ deactivated: boolean; beneficiaryId: string }>> {
140
141
  const url = `${this.baseUrl}/beneficiaries/${encodeURIComponent(beneficiaryId)}/deactivate`;
141
- return await this.httpRequest.post(url, { directoryId });
142
+ return await this.httpRequest.post(url, { directoryId, ...(actor && { actor }) });
142
143
  }
143
144
 
144
145
  async pricingSchedule(directoryId: string, corridor: RemittanceCorridor): Promise<ApiGatewayResponse<PricingScheduleResponse>> {
@@ -247,6 +248,15 @@ export default class UnitellerConnectorApi implements IUnitellerConnectorApi {
247
248
  return await this.httpRequest.get(url, { period });
248
249
  }
249
250
 
251
+ async backofficeStatsRange(request: RemittanceBackofficeStatsRangeRequest): Promise<ApiGatewayResponse<RemittanceBackofficeStats>> {
252
+ const url = `${this.baseUrl}/backoffice/stats`;
253
+ return await this.httpRequest.get(url, {
254
+ from: request.from,
255
+ to: request.to,
256
+ ...(request.tzOffsetMinutes !== undefined && { tzOffsetMinutes: String(request.tzOffsetMinutes) }),
257
+ });
258
+ }
259
+
250
260
  async backofficeUserLimits(directoryId: string): Promise<ApiGatewayResponse<RemittanceUserLimits>> {
251
261
  const url = `${this.baseUrl}/backoffice/users/${encodeURIComponent(directoryId)}/limits`;
252
262
  return await this.httpRequest.get(url);
@@ -24,6 +24,7 @@ import {
24
24
  RemittanceAddBeneficiaryRequest,
25
25
  RemittanceBackofficeDashboardSummary,
26
26
  RemittanceBackofficeStats,
27
+ RemittanceBackofficeStatsRangeRequest,
27
28
  RemittanceBackofficeStatsPeriod,
28
29
  RemittanceBackofficeCancelCloseRequest,
29
30
  RemittanceBackofficeCancelCloseResponse,
@@ -108,9 +109,10 @@ export interface IUnitellerConnectorApi {
108
109
 
109
110
  listBeneficiaries(directoryId: string, includeDeactivated?: boolean): Promise<ApiGatewayResponse<RemittanceListBeneficiariesResponse>>;
110
111
  getBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
111
- addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
112
- updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
113
- deactivateBeneficiary(directoryId: string, beneficiaryId: string): Promise<ApiGatewayResponse<{ deactivated: boolean; beneficiaryId: string }>>;
112
+ /** `actor` opcional ("BACKOFFICE:<email>") cuando la operación no la hace el usuario; queda en createdBy/updatedBy. */
113
+ addBeneficiary(directoryId: string, request: RemittanceAddBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
114
+ updateBeneficiary(directoryId: string, beneficiaryId: string, request: RemittanceUpdateBeneficiaryRequest, actor?: string): Promise<ApiGatewayResponse<RemittanceBeneficiary>>;
115
+ deactivateBeneficiary(directoryId: string, beneficiaryId: string, actor?: string): Promise<ApiGatewayResponse<{ deactivated: boolean; beneficiaryId: string }>>;
114
116
  /** Schedule de tramos de service fee + promo automática por corredor (F2 app; passthrough a remittance-business). POST /pricing/schedule. */
115
117
  pricingSchedule(directoryId: string, corridor: RemittanceCorridor): Promise<ApiGatewayResponse<PricingScheduleResponse>>;
116
118
 
@@ -198,6 +200,8 @@ export interface IUnitellerConnectorApi {
198
200
  /** Cierre manual de una cancelación: UPDATE a UniTeller + credit-back. */
199
201
  backofficeCloseCancellation(txNumber: string, request: RemittanceBackofficeCancelCloseRequest): Promise<ApiGatewayResponse<RemittanceBackofficeCancelCloseResponse>>;
200
202
  backofficeStats(period: RemittanceBackofficeStatsPeriod): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
203
+ /** Stats por rango explícito (from/to ISO) agrupando los días con el desfase del operador. GET /backoffice/stats. */
204
+ backofficeStatsRange(request: RemittanceBackofficeStatsRangeRequest): Promise<ApiGatewayResponse<RemittanceBackofficeStats>>;
201
205
  /** Límites por usuario (Operación · read-only): ventanas (límite del provider + usage) + nivel + discrepancia. */
202
206
  backofficeUserLimits(directoryId: string): Promise<ApiGatewayResponse<RemittanceUserLimits>>;
203
207
  /** Batch de límites para la tabla de Límites (CSV de directoryIds). */