@fiado/api-invoker 4.61.0 → 4.63.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 CHANGED
@@ -76,6 +76,7 @@ export * from "./benefits-marketplace/index.js";
76
76
  export * from "./milestone-business/index.js";
77
77
  export * from "./cognitoBackofficeConnector/index.js";
78
78
  export * from "./platformRbac/index.js";
79
+ export * from "./retailOrg/index.js";
79
80
  export * from "./messages-business/index.js";
80
81
  export * from "./totp-security/index.js";
81
82
  export * from "./equality-connector/index.js";
package/bin/index.js CHANGED
@@ -76,6 +76,7 @@ export * from "./benefits-marketplace/index.js";
76
76
  export * from "./milestone-business/index.js";
77
77
  export * from "./cognitoBackofficeConnector/index.js";
78
78
  export * from "./platformRbac/index.js";
79
+ export * from "./retailOrg/index.js";
79
80
  export * from "./messages-business/index.js";
80
81
  export * from "./totp-security/index.js";
81
82
  export * from "./equality-connector/index.js";
@@ -0,0 +1,28 @@
1
+ import type { IHttpRequest } from "@fiado/http-client";
2
+ import { StandardResponse } from "@fiado/gateway-adapter";
3
+ import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto } from "@fiado/type-kit/bin/retailOrg/index.js";
4
+ import { IRetailOrgBusinessApi } from "./interfaces/IRetailOrgBusinessApi.js";
5
+ /**
6
+ * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 4
7
+ * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
8
+ *
9
+ * Los 4 paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
10
+ * 2026-07-16 y matchean `openapi/private.yaml` del lambda destino.
11
+ *
12
+ * Env var requerida en el consumer: `RETAIL_ORG_BUSINESS_URL`.
13
+ * El template.yml del consumer la setea con:
14
+ *
15
+ * RETAIL_ORG_BUSINESS_URL: '{{resolve:ssm:retail-org-business}}'
16
+ *
17
+ * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
18
+ */
19
+ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
20
+ private httpRequest;
21
+ private readonly baseUrl;
22
+ constructor(httpRequest: IHttpRequest);
23
+ getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
24
+ getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
25
+ getStore(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<StoreValidationDto>>;
26
+ getStoreUsers(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto[]>>;
27
+ getUserByCognitoSub(cognitoSub: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto>>;
28
+ }
@@ -0,0 +1,60 @@
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 `retail-org-business` (componente 04 SureKeep Fase 1) para sus 4
16
+ * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
17
+ *
18
+ * Los 4 paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
19
+ * 2026-07-16 y matchean `openapi/private.yaml` del lambda destino.
20
+ *
21
+ * Env var requerida en el consumer: `RETAIL_ORG_BUSINESS_URL`.
22
+ * El template.yml del consumer la setea con:
23
+ *
24
+ * RETAIL_ORG_BUSINESS_URL: '{{resolve:ssm:retail-org-business}}'
25
+ *
26
+ * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
27
+ */
28
+ let RetailOrgBusinessApi = class RetailOrgBusinessApi {
29
+ httpRequest;
30
+ baseUrl = process.env.RETAIL_ORG_BUSINESS_URL || "";
31
+ constructor(httpRequest) {
32
+ this.httpRequest = httpRequest;
33
+ }
34
+ async getRetailer(retailerId, tenantId) {
35
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
36
+ return await this.httpRequest.get(url);
37
+ }
38
+ async getRetailerByStore(storeId, tenantId) {
39
+ const url = `${this.baseUrl}/private/retailers/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
40
+ return await this.httpRequest.get(url);
41
+ }
42
+ async getStore(retailerId, storeId, tenantId) {
43
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}/stores/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
44
+ return await this.httpRequest.get(url);
45
+ }
46
+ async getStoreUsers(retailerId, storeId, tenantId) {
47
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}/users/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
48
+ return await this.httpRequest.get(url);
49
+ }
50
+ async getUserByCognitoSub(cognitoSub, tenantId) {
51
+ const url = `${this.baseUrl}/private/users/by-cognito-sub/${encodeURIComponent(cognitoSub)}?tenantId=${encodeURIComponent(tenantId)}`;
52
+ return await this.httpRequest.get(url);
53
+ }
54
+ };
55
+ RetailOrgBusinessApi = __decorate([
56
+ injectable(),
57
+ __param(0, inject("IHttpRequest")),
58
+ __metadata("design:paramtypes", [Object])
59
+ ], RetailOrgBusinessApi);
60
+ export default RetailOrgBusinessApi;
@@ -0,0 +1,90 @@
1
+ import { StandardResponse } from "@fiado/gateway-adapter";
2
+ import { RetailerValidationDto, StoreValidationDto, RetailUserValidationDto } from "@fiado/type-kit/bin/retailOrg/index.js";
3
+ /**
4
+ * Contrato del publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1)
5
+ * para sus 4 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
6
+ *
7
+ * Consumidores previstos (regla R5 — cruces entre lambdas son SOLO lecturas de validación;
8
+ * ningún lambda escribe en tabla ajena):
9
+ * - `retail-catalog-business` → valida `storeId` al registrar IMEIs
10
+ * - `retail-cards-business` → valida `storeId` de un lote de tarjetas PCF
11
+ * - `loan-*` → valida retailer / store / usuarios retail
12
+ *
13
+ * ─────────────────────────────────────────────────────────────────────────────
14
+ * `tenantId` es OBLIGATORIO en los 4 métodos — no es un detalle de firma.
15
+ * ─────────────────────────────────────────────────────────────────────────────
16
+ * Los privados NO llevan token de usuario (`Feature.ANONIMUS`; la protección es la red VPC),
17
+ * así que el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller
18
+ * declara el tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo.
19
+ * Sin `tenantId` → `400 UNKNOWN_TENANT` (fail-closed, verificado en dev). Nunca hay default:
20
+ * caer a un tenant por default sería fail-OPEN y podría devolver datos de otra SOFOM.
21
+ *
22
+ * ─────────────────────────────────────────────────────────────────────────────
23
+ * ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
24
+ * ─────────────────────────────────────────────────────────────────────────────
25
+ * Los publishers viejos tipan `ApiGatewayResponse<T>` (`{ statusCode, body }`) y documentan
26
+ * `result.body.data`. Eso es FICCIÓN del tipo: `@fiado/http-client` hace `return response.data`
27
+ * (ver `AxiosHttpRequest`), o sea entrega el BODY PELADO — `.statusCode`/`.body` no existen en
28
+ * runtime y leerlos da `undefined`. Verificado en dev el 2026-07-16: costó un `500` (TypeError sobre
29
+ * `body.roleAssignments`) en `retail-org-business` al confiar en el tipo. `StandardResponse<T>`
30
+ * (`{ code, date, data, description?, msg? }`, ya exportado por `@fiado/gateway-adapter`) SÍ describe
31
+ * lo que llega. No se toca el tipo de los publishers viejos acá para no romperlos, pero los nuevos
32
+ * 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 RETAILER_NOT_FOUND` / `404 STORE_NOT_FOUND` / `404 RETAIL_USER_NOT_FOUND`
37
+ * `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
38
+ *
39
+ * Env var requerida en el consumer: `RETAIL_ORG_BUSINESS_URL`.
40
+ * El template.yml del consumer la setea con:
41
+ *
42
+ * RETAIL_ORG_BUSINESS_URL: '{{resolve:ssm:retail-org-business}}'
43
+ *
44
+ * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
45
+ */
46
+ export interface IRetailOrgBusinessApi {
47
+ /**
48
+ * GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
49
+ * (id, name, type, status, parentId). `status` ya viene con la cascada aplicada (estado efectivo).
50
+ *
51
+ * @throws si el retailer no existe (`404 RETAILER_NOT_FOUND`).
52
+ */
53
+ getRetailer(retailerId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
54
+ /**
55
+ * GET /private/retailers/by-store/{storeId} — resuelve el retailer DUEÑO de una tienda teniendo
56
+ * SOLO el `storeId`, sin conocer el retailer. Es el único privado que no va anidado, porque es el
57
+ * único caso donde el caller no tiene el `retailerId` (spec comp. 04: "resolver retailerId desde
58
+ * storeId").
59
+ *
60
+ * Se apoya en el GSI `storeId-pk-index` de `RetailStore_GT`: sin él haría falta `Scan`, que el rol
61
+ * del tenant prohíbe. Si el índice no está deployado en el silo, este endpoint responde `500`.
62
+ *
63
+ * @throws si la tienda no existe (`404 STORE_NOT_FOUND`).
64
+ */
65
+ getRetailerByStore(storeId: string, tenantId: string): Promise<StandardResponse<RetailerValidationDto>>;
66
+ /**
67
+ * GET /private/retailers/{retailerId}/stores/{storeId} — valida que la tienda exista Y pertenezca
68
+ * a ese retailer. El path es ANIDADO (no `/private/stores/{storeId}`): la tabla es
69
+ * pk `RETAILER#<id>` / sk `STORE#<storeId>`, así que el lookup anidado es un `get(pk, sk)` directo
70
+ * sobre la tabla base — cero GSI. Un path aplanado obligaría a un índice que el spec no define.
71
+ *
72
+ * `status` viene con la cascada del retailer padre ya aplicada.
73
+ *
74
+ * @throws si la tienda no existe o es de OTRO retailer (`404 STORE_NOT_FOUND` — verificado en dev).
75
+ */
76
+ getStore(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<StoreValidationDto>>;
77
+ /**
78
+ * GET /private/retailers/{retailerId}/users/by-store/{storeId} — usuarios retail cuya tienda base
79
+ * (`homeStoreId`) es esa. Devuelve `[]` (no 404) si la tienda no tiene usuarios asignados.
80
+ */
81
+ getStoreUsers(retailerId: string, storeId: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto[]>>;
82
+ /**
83
+ * GET /private/users/by-cognito-sub/{cognitoSub} — resuelve el usuario retail por su identidad
84
+ * Cognito. Es el match de la frontera RBAC (F0, identidad) ↔ retail-org (F1, estructura):
85
+ * el `cognitoSub` es la llave entre ambos mundos (ver `DEC-SKF1-005`).
86
+ *
87
+ * @throws si no hay usuario retail para ese sub (`404 RETAIL_USER_NOT_FOUND`).
88
+ */
89
+ getUserByCognitoSub(cognitoSub: string, tenantId: string): Promise<StandardResponse<RetailUserValidationDto>>;
90
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailOrgBusinessApi.js";
2
+ export { default as RetailOrgBusinessApi } from "./api/RetailOrgBusinessApi.js";
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailOrgBusinessApi.js";
2
+ export { default as RetailOrgBusinessApi } from "./api/RetailOrgBusinessApi.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fiado/api-invoker",
3
- "version": "4.61.0",
3
+ "version": "4.63.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.178.0",
37
+ "@fiado/type-kit": "^3.189.0",
38
38
  "dotenv": "^16.4.7"
39
39
  },
40
40
  "peerDependencies": {
package/src/index.ts CHANGED
@@ -76,6 +76,7 @@ export * from "./benefits-marketplace/index.js";
76
76
  export * from "./milestone-business/index.js";
77
77
  export * from "./cognitoBackofficeConnector/index.js";
78
78
  export * from "./platformRbac/index.js";
79
+ export * from "./retailOrg/index.js";
79
80
  export * from "./messages-business/index.js";
80
81
  export * from "./totp-security/index.js";
81
82
  export * from "./equality-connector/index.js";
@@ -0,0 +1,72 @@
1
+ import { inject, injectable } from "inversify";
2
+ import type { IHttpRequest } from "@fiado/http-client";
3
+ import { StandardResponse } from "@fiado/gateway-adapter";
4
+ import {
5
+ RetailerValidationDto,
6
+ StoreValidationDto,
7
+ RetailUserValidationDto,
8
+ } from "@fiado/type-kit/bin/retailOrg/index.js";
9
+ import { IRetailOrgBusinessApi } from "./interfaces/IRetailOrgBusinessApi.js";
10
+
11
+ /**
12
+ * Publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1) para sus 4
13
+ * endpoints privados de validación. Contrato y semántica completos → `IRetailOrgBusinessApi`.
14
+ *
15
+ * Los 4 paths y el `?tenantId=` fueron verificados contra dev (200 + negativos 400/404) el
16
+ * 2026-07-16 y matchean `openapi/private.yaml` del lambda destino.
17
+ *
18
+ * Env var requerida en el consumer: `RETAIL_ORG_BUSINESS_URL`.
19
+ * El template.yml del consumer la setea con:
20
+ *
21
+ * RETAIL_ORG_BUSINESS_URL: '{{resolve:ssm:retail-org-business}}'
22
+ *
23
+ * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
24
+ */
25
+ @injectable()
26
+ export default class RetailOrgBusinessApi implements IRetailOrgBusinessApi {
27
+ private readonly baseUrl = process.env.RETAIL_ORG_BUSINESS_URL || "";
28
+
29
+ constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
30
+
31
+ async getRetailer(
32
+ retailerId: string,
33
+ tenantId: string,
34
+ ): Promise<StandardResponse<RetailerValidationDto>> {
35
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}?tenantId=${encodeURIComponent(tenantId)}`;
36
+ return await this.httpRequest.get(url);
37
+ }
38
+
39
+ async getRetailerByStore(
40
+ storeId: string,
41
+ tenantId: string,
42
+ ): Promise<StandardResponse<RetailerValidationDto>> {
43
+ const url = `${this.baseUrl}/private/retailers/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
44
+ return await this.httpRequest.get(url);
45
+ }
46
+
47
+ async getStore(
48
+ retailerId: string,
49
+ storeId: string,
50
+ tenantId: string,
51
+ ): Promise<StandardResponse<StoreValidationDto>> {
52
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}/stores/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
53
+ return await this.httpRequest.get(url);
54
+ }
55
+
56
+ async getStoreUsers(
57
+ retailerId: string,
58
+ storeId: string,
59
+ tenantId: string,
60
+ ): Promise<StandardResponse<RetailUserValidationDto[]>> {
61
+ const url = `${this.baseUrl}/private/retailers/${encodeURIComponent(retailerId)}/users/by-store/${encodeURIComponent(storeId)}?tenantId=${encodeURIComponent(tenantId)}`;
62
+ return await this.httpRequest.get(url);
63
+ }
64
+
65
+ async getUserByCognitoSub(
66
+ cognitoSub: string,
67
+ tenantId: string,
68
+ ): Promise<StandardResponse<RetailUserValidationDto>> {
69
+ const url = `${this.baseUrl}/private/users/by-cognito-sub/${encodeURIComponent(cognitoSub)}?tenantId=${encodeURIComponent(tenantId)}`;
70
+ return await this.httpRequest.get(url);
71
+ }
72
+ }
@@ -0,0 +1,116 @@
1
+ import { StandardResponse } from "@fiado/gateway-adapter";
2
+ import {
3
+ RetailerValidationDto,
4
+ StoreValidationDto,
5
+ RetailUserValidationDto,
6
+ } from "@fiado/type-kit/bin/retailOrg/index.js";
7
+
8
+ /**
9
+ * Contrato del publisher HTTP del lambda `retail-org-business` (componente 04 SureKeep Fase 1)
10
+ * para sus 4 endpoints privados de VALIDACIÓN (service-to-service, VPC-only).
11
+ *
12
+ * Consumidores previstos (regla R5 — cruces entre lambdas son SOLO lecturas de validación;
13
+ * ningún lambda escribe en tabla ajena):
14
+ * - `retail-catalog-business` → valida `storeId` al registrar IMEIs
15
+ * - `retail-cards-business` → valida `storeId` de un lote de tarjetas PCF
16
+ * - `loan-*` → valida retailer / store / usuarios retail
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),
22
+ * así que el lambda destino no tiene `AuthContext.issuer` y NO puede inferir el silo. El caller
23
+ * declara el tenant explícito por query y `@fiado/tenant-context` asume el rol de ESE silo.
24
+ * Sin `tenantId` → `400 UNKNOWN_TENANT` (fail-closed, verificado en dev). Nunca hay default:
25
+ * caer a un tenant por default sería fail-OPEN y podría devolver datos de otra SOFOM.
26
+ *
27
+ * ─────────────────────────────────────────────────────────────────────────────
28
+ * ⚠️ Patrón de retorno: `StandardResponse<T>` — el consumer accede `result.data`, NO `result.body`.
29
+ * ─────────────────────────────────────────────────────────────────────────────
30
+ * Los publishers viejos tipan `ApiGatewayResponse<T>` (`{ statusCode, body }`) y documentan
31
+ * `result.body.data`. Eso es FICCIÓN del tipo: `@fiado/http-client` hace `return response.data`
32
+ * (ver `AxiosHttpRequest`), o sea entrega el BODY PELADO — `.statusCode`/`.body` no existen en
33
+ * runtime y leerlos da `undefined`. Verificado en dev el 2026-07-16: costó un `500` (TypeError sobre
34
+ * `body.roleAssignments`) en `retail-org-business` al confiar en el tipo. `StandardResponse<T>`
35
+ * (`{ code, date, data, description?, msg? }`, ya exportado por `@fiado/gateway-adapter`) SÍ describe
36
+ * lo que llega. No se toca el tipo de los publishers viejos acá para no romperlos, pero los nuevos
37
+ * dicen la verdad.
38
+ *
39
+ * Errores: el lambda destino lanza `DomainError` tipado → el publisher RECHAZA (no devuelve null).
40
+ * Cada consumer mapea a su propio error de dominio (ver `fiado-api-invoker § 6`):
41
+ * `404 RETAILER_NOT_FOUND` / `404 STORE_NOT_FOUND` / `404 RETAIL_USER_NOT_FOUND`
42
+ * `400 UNKNOWN_TENANT` (tenantId ausente o desconocido)
43
+ *
44
+ * Env var requerida en el consumer: `RETAIL_ORG_BUSINESS_URL`.
45
+ * El template.yml del consumer la setea con:
46
+ *
47
+ * RETAIL_ORG_BUSINESS_URL: '{{resolve:ssm:retail-org-business}}'
48
+ *
49
+ * Convención CLAUDE.md global: SSM key = nombre del lambda owner de la URL.
50
+ */
51
+ export interface IRetailOrgBusinessApi {
52
+ /**
53
+ * GET /private/retailers/{retailerId} — valida que el retailer exista y devuelve su shape mínimo
54
+ * (id, name, type, status, parentId). `status` ya viene con la cascada aplicada (estado efectivo).
55
+ *
56
+ * @throws si el retailer no existe (`404 RETAILER_NOT_FOUND`).
57
+ */
58
+ getRetailer(
59
+ retailerId: string,
60
+ tenantId: string,
61
+ ): Promise<StandardResponse<RetailerValidationDto>>;
62
+
63
+ /**
64
+ * GET /private/retailers/by-store/{storeId} — resuelve el retailer DUEÑO de una tienda teniendo
65
+ * SOLO el `storeId`, sin conocer el retailer. Es el único privado que no va anidado, porque es el
66
+ * único caso donde el caller no tiene el `retailerId` (spec comp. 04: "resolver retailerId desde
67
+ * storeId").
68
+ *
69
+ * Se apoya en el GSI `storeId-pk-index` de `RetailStore_GT`: sin él haría falta `Scan`, que el rol
70
+ * del tenant prohíbe. Si el índice no está deployado en el silo, este endpoint responde `500`.
71
+ *
72
+ * @throws si la tienda no existe (`404 STORE_NOT_FOUND`).
73
+ */
74
+ getRetailerByStore(
75
+ storeId: string,
76
+ tenantId: string,
77
+ ): Promise<StandardResponse<RetailerValidationDto>>;
78
+
79
+ /**
80
+ * GET /private/retailers/{retailerId}/stores/{storeId} — valida que la tienda exista Y pertenezca
81
+ * a ese retailer. El path es ANIDADO (no `/private/stores/{storeId}`): la tabla es
82
+ * pk `RETAILER#<id>` / sk `STORE#<storeId>`, así que el lookup anidado es un `get(pk, sk)` directo
83
+ * sobre la tabla base — cero GSI. Un path aplanado obligaría a un índice que el spec no define.
84
+ *
85
+ * `status` viene con la cascada del retailer padre ya aplicada.
86
+ *
87
+ * @throws si la tienda no existe o es de OTRO retailer (`404 STORE_NOT_FOUND` — verificado en dev).
88
+ */
89
+ getStore(
90
+ retailerId: string,
91
+ storeId: string,
92
+ tenantId: string,
93
+ ): Promise<StandardResponse<StoreValidationDto>>;
94
+
95
+ /**
96
+ * GET /private/retailers/{retailerId}/users/by-store/{storeId} — usuarios retail cuya tienda base
97
+ * (`homeStoreId`) es esa. Devuelve `[]` (no 404) si la tienda no tiene usuarios asignados.
98
+ */
99
+ getStoreUsers(
100
+ retailerId: string,
101
+ storeId: string,
102
+ tenantId: string,
103
+ ): Promise<StandardResponse<RetailUserValidationDto[]>>;
104
+
105
+ /**
106
+ * GET /private/users/by-cognito-sub/{cognitoSub} — resuelve el usuario retail por su identidad
107
+ * Cognito. Es el match de la frontera RBAC (F0, identidad) ↔ retail-org (F1, estructura):
108
+ * el `cognitoSub` es la llave entre ambos mundos (ver `DEC-SKF1-005`).
109
+ *
110
+ * @throws si no hay usuario retail para ese sub (`404 RETAIL_USER_NOT_FOUND`).
111
+ */
112
+ getUserByCognitoSub(
113
+ cognitoSub: string,
114
+ tenantId: string,
115
+ ): Promise<StandardResponse<RetailUserValidationDto>>;
116
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./api/interfaces/IRetailOrgBusinessApi.js";
2
+ export { default as RetailOrgBusinessApi } from "./api/RetailOrgBusinessApi.js";