permissions-contractx 1.6.0 → 2.0.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.
@@ -1,6 +1,14 @@
1
1
  /**
2
2
  * ContractX Role Constants
3
- * Based on the ODS permissions matrix and auth-service-contract structure
3
+ * ------------------------------------------------------------------------
4
+ * FUENTE DE VERDAD: el servicio de Auth (`contractx-Auth`,
5
+ * `src/common/constants/security.constants.ts` → `ROLES`). Estas constantes
6
+ * DEBEN reflejar exactamente los `code` de rol que Auth emite en el claim
7
+ * `role[]` del JWT. Cualquier divergencia (p. ej. `superadmin` vs `super_admin`,
8
+ * `*_manager` vs `*_resp`) rompe la comparación de roles en los guards.
9
+ *
10
+ * Matriz v5 (14 roles de negocio) + `support`. Reconciliado con Auth (2026-06).
11
+ * ------------------------------------------------------------------------
4
12
  */
5
13
  export declare enum ContractXRoleType {
6
14
  ADMIN = "admin",
@@ -18,23 +26,24 @@ export declare enum ContractXRoleScope {
18
26
  TEAM = "team"
19
27
  }
20
28
  export declare const CONTRACTX_ROLES: {
21
- SUPERADMIN: string;
29
+ SUPER_ADMIN: string;
22
30
  SUPPORT: string;
31
+ CLIENT_SUPERADMIN: string;
23
32
  CLIENT_CONTRACT_ADMIN: string;
24
- CLIENT_PERFORMANCE_MANAGER: string;
25
- CLIENT_FINANCE_MANAGER: string;
26
- CLIENT_REPORTS_MANAGER: string;
27
- CLIENT_RELATIONSHIP_MANAGER: string;
28
- CLIENT_RISK_MANAGER: string;
33
+ CLIENT_PERFORMANCE_RESP: string;
34
+ CLIENT_FINANCE_RESP: string;
35
+ CLIENT_REPORTS_RESP: string;
36
+ CLIENT_RELATIONSHIP_RESP: string;
37
+ CLIENT_RISK_RESP: string;
29
38
  PROVIDER_CONTRACT_ADMIN: string;
30
- PROVIDER_PERFORMANCE_MANAGER: string;
31
- PROVIDER_FINANCE_MANAGER: string;
32
- PROVIDER_REPORTS_MANAGER: string;
33
- PROVIDER_RELATIONSHIP_MANAGER: string;
34
- PROVIDER_RISK_MANAGER: string;
39
+ PROVIDER_PERFORMANCE_RESP: string;
40
+ PROVIDER_FINANCE_RESP: string;
41
+ PROVIDER_REPORTS_RESP: string;
42
+ PROVIDER_RELATIONSHIP_RESP: string;
43
+ PROVIDER_RISK_RESP: string;
35
44
  };
36
45
  export declare const CONTRACTX_ROLE_DEFINITIONS: {
37
- [CONTRACTX_ROLES.SUPERADMIN]: {
46
+ [CONTRACTX_ROLES.SUPER_ADMIN]: {
38
47
  name: string;
39
48
  description: string;
40
49
  type: ContractXRoleType;
@@ -52,6 +61,15 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
52
61
  isSystem: boolean;
53
62
  tenant: string;
54
63
  };
64
+ [CONTRACTX_ROLES.CLIENT_SUPERADMIN]: {
65
+ name: string;
66
+ description: string;
67
+ type: ContractXRoleType;
68
+ scope: ContractXRoleScope;
69
+ level: number;
70
+ isSystem: boolean;
71
+ tenant: string;
72
+ };
55
73
  [CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN]: {
56
74
  name: string;
57
75
  description: string;
@@ -61,7 +79,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
61
79
  isSystem: boolean;
62
80
  tenant: string;
63
81
  };
64
- [CONTRACTX_ROLES.CLIENT_PERFORMANCE_MANAGER]: {
82
+ [CONTRACTX_ROLES.CLIENT_PERFORMANCE_RESP]: {
65
83
  name: string;
66
84
  description: string;
67
85
  type: ContractXRoleType;
@@ -70,7 +88,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
70
88
  isSystem: boolean;
71
89
  tenant: string;
72
90
  };
73
- [CONTRACTX_ROLES.CLIENT_FINANCE_MANAGER]: {
91
+ [CONTRACTX_ROLES.CLIENT_FINANCE_RESP]: {
74
92
  name: string;
75
93
  description: string;
76
94
  type: ContractXRoleType;
@@ -79,7 +97,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
79
97
  isSystem: boolean;
80
98
  tenant: string;
81
99
  };
82
- [CONTRACTX_ROLES.CLIENT_REPORTS_MANAGER]: {
100
+ [CONTRACTX_ROLES.CLIENT_REPORTS_RESP]: {
83
101
  name: string;
84
102
  description: string;
85
103
  type: ContractXRoleType;
@@ -88,7 +106,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
88
106
  isSystem: boolean;
89
107
  tenant: string;
90
108
  };
91
- [CONTRACTX_ROLES.CLIENT_RELATIONSHIP_MANAGER]: {
109
+ [CONTRACTX_ROLES.CLIENT_RELATIONSHIP_RESP]: {
92
110
  name: string;
93
111
  description: string;
94
112
  type: ContractXRoleType;
@@ -97,7 +115,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
97
115
  isSystem: boolean;
98
116
  tenant: string;
99
117
  };
100
- [CONTRACTX_ROLES.CLIENT_RISK_MANAGER]: {
118
+ [CONTRACTX_ROLES.CLIENT_RISK_RESP]: {
101
119
  name: string;
102
120
  description: string;
103
121
  type: ContractXRoleType;
@@ -115,7 +133,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
115
133
  isSystem: boolean;
116
134
  tenant: string;
117
135
  };
118
- [CONTRACTX_ROLES.PROVIDER_PERFORMANCE_MANAGER]: {
136
+ [CONTRACTX_ROLES.PROVIDER_PERFORMANCE_RESP]: {
119
137
  name: string;
120
138
  description: string;
121
139
  type: ContractXRoleType;
@@ -124,7 +142,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
124
142
  isSystem: boolean;
125
143
  tenant: string;
126
144
  };
127
- [CONTRACTX_ROLES.PROVIDER_FINANCE_MANAGER]: {
145
+ [CONTRACTX_ROLES.PROVIDER_FINANCE_RESP]: {
128
146
  name: string;
129
147
  description: string;
130
148
  type: ContractXRoleType;
@@ -133,7 +151,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
133
151
  isSystem: boolean;
134
152
  tenant: string;
135
153
  };
136
- [CONTRACTX_ROLES.PROVIDER_REPORTS_MANAGER]: {
154
+ [CONTRACTX_ROLES.PROVIDER_REPORTS_RESP]: {
137
155
  name: string;
138
156
  description: string;
139
157
  type: ContractXRoleType;
@@ -142,7 +160,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
142
160
  isSystem: boolean;
143
161
  tenant: string;
144
162
  };
145
- [CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_MANAGER]: {
163
+ [CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_RESP]: {
146
164
  name: string;
147
165
  description: string;
148
166
  type: ContractXRoleType;
@@ -151,7 +169,7 @@ export declare const CONTRACTX_ROLE_DEFINITIONS: {
151
169
  isSystem: boolean;
152
170
  tenant: string;
153
171
  };
154
- [CONTRACTX_ROLES.PROVIDER_RISK_MANAGER]: {
172
+ [CONTRACTX_ROLES.PROVIDER_RISK_RESP]: {
155
173
  name: string;
156
174
  description: string;
157
175
  type: ContractXRoleType;
@@ -1 +1 @@
1
- {"version":3,"file":"contractx-roles.constants.d.ts","sourceRoot":"","sources":["../../src/constants/contractx-roles.constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,oBAAY,iBAAiB;IAC3B,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;CAkB3B,CAAC;AAEF,eAAO,MAAM,0BAA0B;IACnC,CAAC,eAAe,CAAC,UAAU,CAAC;;;;;;;;MAQ3B;IACD,CAAC,eAAe,CAAC,OAAO,CAAC;;;;;;;;MAQxB;IAED,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;MAQtC;IACD,CAAC,eAAe,CAAC,0BAA0B,CAAC;;;;;;;;MAQ3C;IACD,CAAC,eAAe,CAAC,sBAAsB,CAAC;;;;;;;;MAQvC;IACD,CAAC,eAAe,CAAC,sBAAsB,CAAC;;;;;;;;MAQvC;IACD,CAAC,eAAe,CAAC,2BAA2B,CAAC;;;;;;;;MAQ5C;IACD,CAAC,eAAe,CAAC,mBAAmB,CAAC;;;;;;;;MAQpC;IAED,CAAC,eAAe,CAAC,uBAAuB,CAAC;;;;;;;;MAQxC;IACD,CAAC,eAAe,CAAC,4BAA4B,CAAC;;;;;;;;MAQ7C;IACD,CAAC,eAAe,CAAC,wBAAwB,CAAC;;;;;;;;MAQzC;IACD,CAAC,eAAe,CAAC,wBAAwB,CAAC;;;;;;;;MAQzC;IACD,CAAC,eAAe,CAAC,6BAA6B,CAAC;;;;;;;;MAQ9C;IACD,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;MAQtC;CACJ,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAiC,CAAC;AAEpE,eAAO,MAAM,qBAAqB;;;;;;CA+BjC,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AACF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AACF,eAAO,MAAM,cAAc,GAAI,SAAI,YAElC,CAAC;AACF,eAAO,MAAM,WAAW,GAAI,SAAI,YAE/B,CAAC;AACF,eAAO,MAAM,eAAe,GAAI,SAAI;;;;;;;;CAEnC,CAAC;AACF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AAIF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AACnF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACtF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACtF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,qBAAqB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1F,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"contractx-roles.constants.d.ts","sourceRoot":"","sources":["../../src/constants/contractx-roles.constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,oBAAY,iBAAiB;IAC3B,KAAK,UAAU;IACf,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,oBAAY,kBAAkB;IAC5B,MAAM,WAAW;IACjB,YAAY,iBAAiB;IAC7B,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,IAAI,SAAS;CACd;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;CAmB3B,CAAC;AAEF,eAAO,MAAM,0BAA0B;IACnC,CAAC,eAAe,CAAC,WAAW,CAAC;;;;;;;;MAQ5B;IACD,CAAC,eAAe,CAAC,OAAO,CAAC;;;;;;;;MAQxB;IAED,CAAC,eAAe,CAAC,iBAAiB,CAAC;;;;;;;;MAQlC;IACD,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;MAQtC;IACD,CAAC,eAAe,CAAC,uBAAuB,CAAC;;;;;;;;MAQxC;IACD,CAAC,eAAe,CAAC,mBAAmB,CAAC;;;;;;;;MAQpC;IACD,CAAC,eAAe,CAAC,mBAAmB,CAAC;;;;;;;;MAQpC;IACD,CAAC,eAAe,CAAC,wBAAwB,CAAC;;;;;;;;MAQzC;IACD,CAAC,eAAe,CAAC,gBAAgB,CAAC;;;;;;;;MAQjC;IAED,CAAC,eAAe,CAAC,uBAAuB,CAAC;;;;;;;;MAQxC;IACD,CAAC,eAAe,CAAC,yBAAyB,CAAC;;;;;;;;MAQ1C;IACD,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;MAQtC;IACD,CAAC,eAAe,CAAC,qBAAqB,CAAC;;;;;;;;MAQtC;IACD,CAAC,eAAe,CAAC,0BAA0B,CAAC;;;;;;;;MAQ3C;IACD,CAAC,eAAe,CAAC,kBAAkB,CAAC;;;;;;;;MAQnC;CACJ,CAAC;AAEF,eAAO,MAAM,qBAAqB,UAAiC,CAAC;AAEpE,eAAO,MAAM,qBAAqB;;;;;;CAiCjC,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AACF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AACF,eAAO,MAAM,cAAc,GAAI,SAAI,YAElC,CAAC;AACF,eAAO,MAAM,WAAW,GAAI,SAAI,YAE/B,CAAC;AACF,eAAO,MAAM,eAAe,GAAI,SAAI;;;;;;;;CAEnC,CAAC;AACF,eAAO,MAAM,YAAY,GAAI,SAAI,YAEhC,CAAC;AAIF,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AACnF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACtF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,qBAAqB,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AACtF,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,qBAAqB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAC1F,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC"}
@@ -3,7 +3,15 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateRole = exports.getRoleMetadata = exports.isAdminRole = exports.isProviderRole = exports.isClientRole = exports.isSystemRole = exports.CONTRACTX_ROLE_GROUPS = exports.VALID_CONTRACTX_ROLES = exports.CONTRACTX_ROLE_DEFINITIONS = exports.CONTRACTX_ROLES = exports.ContractXRoleScope = exports.ContractXRoleType = void 0;
4
4
  /**
5
5
  * ContractX Role Constants
6
- * Based on the ODS permissions matrix and auth-service-contract structure
6
+ * ------------------------------------------------------------------------
7
+ * FUENTE DE VERDAD: el servicio de Auth (`contractx-Auth`,
8
+ * `src/common/constants/security.constants.ts` → `ROLES`). Estas constantes
9
+ * DEBEN reflejar exactamente los `code` de rol que Auth emite en el claim
10
+ * `role[]` del JWT. Cualquier divergencia (p. ej. `superadmin` vs `super_admin`,
11
+ * `*_manager` vs `*_resp`) rompe la comparación de roles en los guards.
12
+ *
13
+ * Matriz v5 (14 roles de negocio) + `support`. Reconciliado con Auth (2026-06).
14
+ * ------------------------------------------------------------------------
7
15
  */
8
16
  // Role Types from auth-service
9
17
  var ContractXRoleType;
@@ -24,29 +32,30 @@ var ContractXRoleScope;
24
32
  ContractXRoleScope["DEPARTMENT"] = "department";
25
33
  ContractXRoleScope["TEAM"] = "team";
26
34
  })(ContractXRoleScope || (exports.ContractXRoleScope = ContractXRoleScope = {}));
27
- // Standard ContractX Roles (based on ODS matrix)
35
+ // Roles canónicos de ContractX codes IDÉNTICOS a `ROLES` de Auth.
28
36
  exports.CONTRACTX_ROLES = {
29
- // System Roles
30
- SUPERADMIN: 'superadmin',
37
+ // System
38
+ SUPER_ADMIN: 'super_admin',
31
39
  SUPPORT: 'support',
32
- // Client-Side Roles
40
+ // Client-Side
41
+ CLIENT_SUPERADMIN: 'client_superadmin',
33
42
  CLIENT_CONTRACT_ADMIN: 'client_contract_admin',
34
- CLIENT_PERFORMANCE_MANAGER: 'client_performance_manager',
35
- CLIENT_FINANCE_MANAGER: 'client_finance_manager',
36
- CLIENT_REPORTS_MANAGER: 'client_reports_manager',
37
- CLIENT_RELATIONSHIP_MANAGER: 'client_relationship_manager',
38
- CLIENT_RISK_MANAGER: 'client_risk_manager',
39
- // Provider-Side Roles
43
+ CLIENT_PERFORMANCE_RESP: 'client_performance_resp',
44
+ CLIENT_FINANCE_RESP: 'client_finance_resp',
45
+ CLIENT_REPORTS_RESP: 'client_reports_resp',
46
+ CLIENT_RELATIONSHIP_RESP: 'client_relationship_resp',
47
+ CLIENT_RISK_RESP: 'client_risk_resp',
48
+ // Provider-Side
40
49
  PROVIDER_CONTRACT_ADMIN: 'provider_contract_admin',
41
- PROVIDER_PERFORMANCE_MANAGER: 'provider_performance_manager',
42
- PROVIDER_FINANCE_MANAGER: 'provider_finance_manager',
43
- PROVIDER_REPORTS_MANAGER: 'provider_reports_manager',
44
- PROVIDER_RELATIONSHIP_MANAGER: 'provider_relationship_manager',
45
- PROVIDER_RISK_MANAGER: 'provider_risk_manager',
50
+ PROVIDER_PERFORMANCE_RESP: 'provider_performance_resp',
51
+ PROVIDER_FINANCE_RESP: 'provider_finance_resp',
52
+ PROVIDER_REPORTS_RESP: 'provider_reports_resp',
53
+ PROVIDER_RELATIONSHIP_RESP: 'provider_relationship_resp',
54
+ PROVIDER_RISK_RESP: 'provider_risk_resp',
46
55
  };
47
56
  // Role Definitions with metadata
48
57
  exports.CONTRACTX_ROLE_DEFINITIONS = {
49
- [exports.CONTRACTX_ROLES.SUPERADMIN]: {
58
+ [exports.CONTRACTX_ROLES.SUPER_ADMIN]: {
50
59
  name: 'Super Administrator',
51
60
  description: 'Full system access with all permissions',
52
61
  type: ContractXRoleType.ADMIN,
@@ -65,6 +74,15 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
65
74
  tenant: 'system'
66
75
  },
67
76
  // Client Roles
77
+ [exports.CONTRACTX_ROLES.CLIENT_SUPERADMIN]: {
78
+ name: 'Super Admin Cliente',
79
+ description: 'Administrador máximo por cliente (S-CL)',
80
+ type: ContractXRoleType.ADMIN,
81
+ scope: ContractXRoleScope.ORGANIZATION,
82
+ level: 9,
83
+ isSystem: false,
84
+ tenant: 'client'
85
+ },
68
86
  [exports.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN]: {
69
87
  name: 'Client Contract Administrator',
70
88
  description: 'Full contract management for client organization',
@@ -74,8 +92,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
74
92
  isSystem: false,
75
93
  tenant: 'client'
76
94
  },
77
- [exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_MANAGER]: {
78
- name: 'Client Performance Manager',
95
+ [exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_RESP]: {
96
+ name: 'Client Performance Responsible',
79
97
  description: 'Performance monitoring and SLA management',
80
98
  type: ContractXRoleType.OPERATOR,
81
99
  scope: ContractXRoleScope.PROJECT,
@@ -83,8 +101,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
83
101
  isSystem: false,
84
102
  tenant: 'client'
85
103
  },
86
- [exports.CONTRACTX_ROLES.CLIENT_FINANCE_MANAGER]: {
87
- name: 'Client Finance Manager',
104
+ [exports.CONTRACTX_ROLES.CLIENT_FINANCE_RESP]: {
105
+ name: 'Client Finance Responsible',
88
106
  description: 'Financial management and invoice oversight',
89
107
  type: ContractXRoleType.OPERATOR,
90
108
  scope: ContractXRoleScope.PROJECT,
@@ -92,8 +110,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
92
110
  isSystem: false,
93
111
  tenant: 'client'
94
112
  },
95
- [exports.CONTRACTX_ROLES.CLIENT_REPORTS_MANAGER]: {
96
- name: 'Client Reports Manager',
113
+ [exports.CONTRACTX_ROLES.CLIENT_REPORTS_RESP]: {
114
+ name: 'Client Reports Responsible',
97
115
  description: 'Reporting and analytics access',
98
116
  type: ContractXRoleType.VIEWER,
99
117
  scope: ContractXRoleScope.PROJECT,
@@ -101,8 +119,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
101
119
  isSystem: false,
102
120
  tenant: 'client'
103
121
  },
104
- [exports.CONTRACTX_ROLES.CLIENT_RELATIONSHIP_MANAGER]: {
105
- name: 'Client Relationship Manager',
122
+ [exports.CONTRACTX_ROLES.CLIENT_RELATIONSHIP_RESP]: {
123
+ name: 'Client Relationship Responsible',
106
124
  description: 'Relationship management and meeting coordination',
107
125
  type: ContractXRoleType.OPERATOR,
108
126
  scope: ContractXRoleScope.PROJECT,
@@ -110,8 +128,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
110
128
  isSystem: false,
111
129
  tenant: 'client'
112
130
  },
113
- [exports.CONTRACTX_ROLES.CLIENT_RISK_MANAGER]: {
114
- name: 'Client Risk Manager',
131
+ [exports.CONTRACTX_ROLES.CLIENT_RISK_RESP]: {
132
+ name: 'Client Risk Responsible',
115
133
  description: 'Risk assessment and escalation management',
116
134
  type: ContractXRoleType.OPERATOR,
117
135
  scope: ContractXRoleScope.PROJECT,
@@ -129,8 +147,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
129
147
  isSystem: false,
130
148
  tenant: 'provider'
131
149
  },
132
- [exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_MANAGER]: {
133
- name: 'Provider Performance Manager',
150
+ [exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_RESP]: {
151
+ name: 'Provider Performance Responsible',
134
152
  description: 'Performance delivery and SLA compliance',
135
153
  type: ContractXRoleType.OPERATOR,
136
154
  scope: ContractXRoleScope.PROJECT,
@@ -138,8 +156,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
138
156
  isSystem: false,
139
157
  tenant: 'provider'
140
158
  },
141
- [exports.CONTRACTX_ROLES.PROVIDER_FINANCE_MANAGER]: {
142
- name: 'Provider Finance Manager',
159
+ [exports.CONTRACTX_ROLES.PROVIDER_FINANCE_RESP]: {
160
+ name: 'Provider Finance Responsible',
143
161
  description: 'Financial management from provider side',
144
162
  type: ContractXRoleType.OPERATOR,
145
163
  scope: ContractXRoleScope.PROJECT,
@@ -147,8 +165,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
147
165
  isSystem: false,
148
166
  tenant: 'provider'
149
167
  },
150
- [exports.CONTRACTX_ROLES.PROVIDER_REPORTS_MANAGER]: {
151
- name: 'Provider Reports Manager',
168
+ [exports.CONTRACTX_ROLES.PROVIDER_REPORTS_RESP]: {
169
+ name: 'Provider Reports Responsible',
152
170
  description: 'Provider reporting capabilities',
153
171
  type: ContractXRoleType.VIEWER,
154
172
  scope: ContractXRoleScope.PROJECT,
@@ -156,8 +174,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
156
174
  isSystem: false,
157
175
  tenant: 'provider'
158
176
  },
159
- [exports.CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_MANAGER]: {
160
- name: 'Provider Relationship Manager',
177
+ [exports.CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_RESP]: {
178
+ name: 'Provider Relationship Responsible',
161
179
  description: 'Client relationship management from provider side',
162
180
  type: ContractXRoleType.OPERATOR,
163
181
  scope: ContractXRoleScope.PROJECT,
@@ -165,8 +183,8 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
165
183
  isSystem: false,
166
184
  tenant: 'provider'
167
185
  },
168
- [exports.CONTRACTX_ROLES.PROVIDER_RISK_MANAGER]: {
169
- name: 'Provider Risk Manager',
186
+ [exports.CONTRACTX_ROLES.PROVIDER_RISK_RESP]: {
187
+ name: 'Provider Risk Responsible',
170
188
  description: 'Risk management from provider perspective',
171
189
  type: ContractXRoleType.OPERATOR,
172
190
  scope: ContractXRoleScope.PROJECT,
@@ -179,35 +197,37 @@ exports.CONTRACTX_ROLE_DEFINITIONS = {
179
197
  exports.VALID_CONTRACTX_ROLES = Object.values(exports.CONTRACTX_ROLES);
180
198
  // Role groups for easier management
181
199
  exports.CONTRACTX_ROLE_GROUPS = {
182
- SYSTEM_ROLES: [exports.CONTRACTX_ROLES.SUPERADMIN, exports.CONTRACTX_ROLES.SUPPORT],
200
+ SYSTEM_ROLES: [exports.CONTRACTX_ROLES.SUPER_ADMIN, exports.CONTRACTX_ROLES.SUPPORT],
183
201
  CLIENT_ROLES: [
202
+ exports.CONTRACTX_ROLES.CLIENT_SUPERADMIN,
184
203
  exports.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN,
185
- exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_MANAGER,
186
- exports.CONTRACTX_ROLES.CLIENT_FINANCE_MANAGER,
187
- exports.CONTRACTX_ROLES.CLIENT_REPORTS_MANAGER,
188
- exports.CONTRACTX_ROLES.CLIENT_RELATIONSHIP_MANAGER,
189
- exports.CONTRACTX_ROLES.CLIENT_RISK_MANAGER,
204
+ exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_RESP,
205
+ exports.CONTRACTX_ROLES.CLIENT_FINANCE_RESP,
206
+ exports.CONTRACTX_ROLES.CLIENT_REPORTS_RESP,
207
+ exports.CONTRACTX_ROLES.CLIENT_RELATIONSHIP_RESP,
208
+ exports.CONTRACTX_ROLES.CLIENT_RISK_RESP,
190
209
  ],
191
210
  PROVIDER_ROLES: [
192
211
  exports.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN,
193
- exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_MANAGER,
194
- exports.CONTRACTX_ROLES.PROVIDER_FINANCE_MANAGER,
195
- exports.CONTRACTX_ROLES.PROVIDER_REPORTS_MANAGER,
196
- exports.CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_MANAGER,
197
- exports.CONTRACTX_ROLES.PROVIDER_RISK_MANAGER,
212
+ exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_RESP,
213
+ exports.CONTRACTX_ROLES.PROVIDER_FINANCE_RESP,
214
+ exports.CONTRACTX_ROLES.PROVIDER_REPORTS_RESP,
215
+ exports.CONTRACTX_ROLES.PROVIDER_RELATIONSHIP_RESP,
216
+ exports.CONTRACTX_ROLES.PROVIDER_RISK_RESP,
198
217
  ],
199
218
  ADMIN_ROLES: [
200
- exports.CONTRACTX_ROLES.SUPERADMIN,
219
+ exports.CONTRACTX_ROLES.SUPER_ADMIN,
220
+ exports.CONTRACTX_ROLES.CLIENT_SUPERADMIN,
201
221
  exports.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN,
202
222
  exports.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN,
203
223
  ],
204
224
  MANAGER_ROLES: [
205
225
  exports.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN,
206
226
  exports.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN,
207
- exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_MANAGER,
208
- exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_MANAGER,
209
- exports.CONTRACTX_ROLES.CLIENT_FINANCE_MANAGER,
210
- exports.CONTRACTX_ROLES.PROVIDER_FINANCE_MANAGER,
227
+ exports.CONTRACTX_ROLES.CLIENT_PERFORMANCE_RESP,
228
+ exports.CONTRACTX_ROLES.PROVIDER_PERFORMANCE_RESP,
229
+ exports.CONTRACTX_ROLES.CLIENT_FINANCE_RESP,
230
+ exports.CONTRACTX_ROLES.PROVIDER_FINANCE_RESP,
211
231
  ],
212
232
  };
213
233
  // Helper functions
@@ -19,7 +19,7 @@ exports.MODULE_CONSTANTS = exports.ROLE_GROUPS = exports.PERMISSION_CATEGORIES =
19
19
  */
20
20
  exports.CONTRACTX_ROLES = {
21
21
  // === SYSTEM ROLE ===
22
- SUPERADMIN: 'superadmin', // ID: 1 - Full access to all modules
22
+ SUPERADMIN: 'super_admin', // ID: 1 - Full access to all modules
23
23
  // === CLIENT-SIDE ROLES ===
24
24
  CLIENT_CONTRACT_ADMIN: 'client_contract_admin', // ID: 2 - Full contract management for assigned client
25
25
  CLIENT_PERFORMANCE_RESP: 'client_performance_resp', // ID: 3 - Performance responsibility role
@@ -0,0 +1,25 @@
1
+ /**
2
+ * [Permisos por contrato] Marca un endpoint como SCOPED a un contrato.
3
+ *
4
+ * El `AuthorizationGuard` exige que el contrato sobre el que opera la petición
5
+ * coincida con el `currentContractId` del JWT (el contrato activo que el usuario
6
+ * seleccionó en Auth). Si no coincide → 403. Esto evita usar un token scopeado al
7
+ * contrato A para operar sobre el contrato B.
8
+ *
9
+ * `path` indica de dónde extraer el contractId de la request, en formato
10
+ * `<fuente>.<campo>` (p. ej. `'params.id'`, `'params.contractId'`,
11
+ * `'body.contractId'`, `'query.contractId'`). Si se omite, el guard prueba en orden:
12
+ * `params.contractId` → `params.id` → `body.contractId` → `query.contractId`.
13
+ *
14
+ * Roles de sistema/globales (`tenantContext='system'` o `super_admin`) hacen bypass
15
+ * del binding (pueden operar sin contrato activo).
16
+ *
17
+ * @example
18
+ * @RequirePermissions(CONTRATOS_PERMISSIONS.CONTRACTS_APPROVE)
19
+ * @ContractScoped('params.id')
20
+ * @Patch(':id/approve')
21
+ * approve(@Param('id') id: string) { ... }
22
+ */
23
+ export declare const CONTRACT_SCOPED_KEY = "contract_scoped";
24
+ export declare const ContractScoped: (path?: string) => import("@nestjs/common").CustomDecorator<string>;
25
+ //# sourceMappingURL=contract-scoped.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-scoped.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/contract-scoped.decorator.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,qDAAiD,CAAC"}
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContractScoped = exports.CONTRACT_SCOPED_KEY = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ /**
6
+ * [Permisos por contrato] Marca un endpoint como SCOPED a un contrato.
7
+ *
8
+ * El `AuthorizationGuard` exige que el contrato sobre el que opera la petición
9
+ * coincida con el `currentContractId` del JWT (el contrato activo que el usuario
10
+ * seleccionó en Auth). Si no coincide → 403. Esto evita usar un token scopeado al
11
+ * contrato A para operar sobre el contrato B.
12
+ *
13
+ * `path` indica de dónde extraer el contractId de la request, en formato
14
+ * `<fuente>.<campo>` (p. ej. `'params.id'`, `'params.contractId'`,
15
+ * `'body.contractId'`, `'query.contractId'`). Si se omite, el guard prueba en orden:
16
+ * `params.contractId` → `params.id` → `body.contractId` → `query.contractId`.
17
+ *
18
+ * Roles de sistema/globales (`tenantContext='system'` o `super_admin`) hacen bypass
19
+ * del binding (pueden operar sin contrato activo).
20
+ *
21
+ * @example
22
+ * @RequirePermissions(CONTRATOS_PERMISSIONS.CONTRACTS_APPROVE)
23
+ * @ContractScoped('params.id')
24
+ * @Patch(':id/approve')
25
+ * approve(@Param('id') id: string) { ... }
26
+ */
27
+ exports.CONTRACT_SCOPED_KEY = 'contract_scoped';
28
+ const ContractScoped = (path) => (0, common_1.SetMetadata)(exports.CONTRACT_SCOPED_KEY, path ?? '');
29
+ exports.ContractScoped = ContractScoped;
@@ -3,4 +3,5 @@ export * from './roles.decorator';
3
3
  export * from './permissions.decorator';
4
4
  export * from './current-user.decorator';
5
5
  export * from './permission-writes.decorator';
6
+ export * from './contract-scoped.decorator';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,6BAA6B,CAAC"}
@@ -19,3 +19,4 @@ __exportStar(require("./roles.decorator"), exports);
19
19
  __exportStar(require("./permissions.decorator"), exports);
20
20
  __exportStar(require("./current-user.decorator"), exports);
21
21
  __exportStar(require("./permission-writes.decorator"), exports);
22
+ __exportStar(require("./contract-scoped.decorator"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"roles.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/roles.decorator.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,MAAM,EAAE,qDAAkC,CAAC;AAK3E,mDAAmD;AACnD,eAAO,MAAM,SAAS,wDAAgF,CAAC;AAEvG,2CAA2C;AAC3C,eAAO,MAAM,UAAU,wDAQpB,CAAC;AAEJ,6CAA6C;AAC7C,eAAO,MAAM,YAAY,wDAQtB,CAAC;AAEJ,2CAA2C;AAC3C,eAAO,MAAM,cAAc,wDAA4B,CAAC;AAExD;;;GAGG;AACH,eAAO,MAAM,YAAY,aArCO,MAAM,EAAE,qDAqCP,CAAC"}
1
+ {"version":3,"file":"roles.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/roles.decorator.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,SAAS,UAAU,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,MAAM,EAAE,qDAAkC,CAAC;AAK3E,mDAAmD;AACnD,eAAO,MAAM,SAAS,wDAAoD,CAAC;AAE3E,2CAA2C;AAC3C,eAAO,MAAM,UAAU,wDAAqD,CAAC;AAE7E,6CAA6C;AAC7C,eAAO,MAAM,YAAY,wDAAuD,CAAC;AAEjF,2CAA2C;AAC3C,eAAO,MAAM,cAAc,wDAA2C,CAAC;AAEvE;;;GAGG;AACH,eAAO,MAAM,YAAY,aArBO,MAAM,EAAE,qDAqBP,CAAC"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RequireRoles = exports.SuperAdminOnly = exports.ProviderOnly = exports.ClientOnly = exports.AdminOnly = exports.Roles = exports.ROLES_KEY = void 0;
4
4
  const common_1 = require("@nestjs/common");
5
+ const contractx_roles_constants_1 = require("../constants/contractx-roles.constants");
5
6
  /**
6
7
  * Metadata key for required roles
7
8
  */
@@ -15,19 +16,19 @@ exports.ROLES_KEY = 'roles';
15
16
  */
16
17
  const Roles = (...roles) => (0, common_1.SetMetadata)(exports.ROLES_KEY, roles);
17
18
  exports.Roles = Roles;
18
- // NOTA[reconstrucción]: los helpers de abajo hardcodean nombres de rol del vocabulario VIEJO
19
- // (superadmin, client_performance_manager, ...) "se reemplaza" al portar al modelo nuevo.
19
+ // Los helpers derivan de CONTRACTX_ROLES / CONTRACTX_ROLE_GROUPS (fuente única reconciliada
20
+ // con los codes de rol de Auth). NO hardcodear literales aquí.
20
21
  /** Decorator for ContractX specific admin roles */
21
- const AdminOnly = () => (0, exports.Roles)('superadmin', 'client_contract_admin', 'provider_contract_admin');
22
+ const AdminOnly = () => (0, exports.Roles)(...contractx_roles_constants_1.CONTRACTX_ROLE_GROUPS.ADMIN_ROLES);
22
23
  exports.AdminOnly = AdminOnly;
23
24
  /** Decorator for client-side roles only */
24
- const ClientOnly = () => (0, exports.Roles)('client_contract_admin', 'client_performance_manager', 'client_finance_manager', 'client_reports_manager', 'client_relationship_manager', 'client_risk_manager');
25
+ const ClientOnly = () => (0, exports.Roles)(...contractx_roles_constants_1.CONTRACTX_ROLE_GROUPS.CLIENT_ROLES);
25
26
  exports.ClientOnly = ClientOnly;
26
27
  /** Decorator for provider-side roles only */
27
- const ProviderOnly = () => (0, exports.Roles)('provider_contract_admin', 'provider_performance_manager', 'provider_finance_manager', 'provider_reports_manager', 'provider_relationship_manager', 'provider_risk_manager');
28
+ const ProviderOnly = () => (0, exports.Roles)(...contractx_roles_constants_1.CONTRACTX_ROLE_GROUPS.PROVIDER_ROLES);
28
29
  exports.ProviderOnly = ProviderOnly;
29
30
  /** Decorator for superadmin access only */
30
- const SuperAdminOnly = () => (0, exports.Roles)('superadmin');
31
+ const SuperAdminOnly = () => (0, exports.Roles)(contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN);
31
32
  exports.SuperAdminOnly = SuperAdminOnly;
32
33
  /**
33
34
  * Alias for Roles decorator for backward compatibility
@@ -33,5 +33,19 @@ export declare class AuthorizationGuard implements CanActivate {
33
33
  * (GET/HEAD/OPTIONS = lectura; el resto = escritura).
34
34
  */
35
35
  private isWriteRequest;
36
+ /**
37
+ * [Permisos por contrato] Verifica que el contrato sobre el que opera la petición
38
+ * coincida con el `currentContractId` del token. Lanza ForbiddenException si no hay
39
+ * contrato activo, no se puede resolver el contrato de la request, o no coinciden.
40
+ */
41
+ private assertContractBinding;
42
+ /** Roles de sistema/globales que pueden operar sin contrato activo (bypass del binding). */
43
+ private isGlobalBypass;
44
+ /**
45
+ * Extrae el contractId de la request. `path` en formato '<fuente>.<campo>'
46
+ * (params/body/query). Si está vacío, prueba ubicaciones comunes en orden:
47
+ * params.contractId → params.id → body.contractId → query.contractId.
48
+ */
49
+ private extractContractId;
36
50
  }
37
51
  //# sourceMappingURL=authorization.guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"authorization.guard.d.ts","sourceRoot":"","sources":["../../src/guards/authorization.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAWzC;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,kBAAmB,YAAW,WAAW;IAGxC,OAAO,CAAC,SAAS;IAF7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAE1C,SAAS,EAAE,SAAS;IAExC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;IA+G/C;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;;;OAIG;IACH,OAAO,CAAC,cAAc;CAUvB"}
1
+ {"version":3,"file":"authorization.guard.d.ts","sourceRoot":"","sources":["../../src/guards/authorization.guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,WAAW,EACX,gBAAgB,EAGjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,kBAAmB,YAAW,WAAW;IAGxC,OAAO,CAAC,SAAS;IAF7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;gBAE1C,SAAS,EAAE,SAAS;IAExC,WAAW,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO;IA6H/C;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAK9B;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAWtB;;;;OAIG;IACH,OAAO,CAAC,qBAAqB;IAqB7B,4FAA4F;IAC5F,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CAe1B"}
@@ -14,6 +14,8 @@ exports.AuthorizationGuard = void 0;
14
14
  const common_1 = require("@nestjs/common");
15
15
  const core_1 = require("@nestjs/core");
16
16
  const permission_writes_decorator_1 = require("../decorators/permission-writes.decorator");
17
+ const contract_scoped_decorator_1 = require("../decorators/contract-scoped.decorator");
18
+ const contractx_roles_constants_1 = require("../constants/contractx-roles.constants");
17
19
  const READ_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
18
20
  /**
19
21
  * [ADR-004] AuthorizationGuard — guard de 4 estados portado desde Auth.
@@ -46,7 +48,14 @@ let AuthorizationGuard = AuthorizationGuard_1 = class AuthorizationGuard {
46
48
  context.getHandler(),
47
49
  context.getClass(),
48
50
  ]);
49
- if ((!requiredRoles || requiredRoles.length === 0) &&
51
+ // [Permisos por contrato] ¿el endpoint está scopeado a un contrato? (metadata presente)
52
+ const contractScopedPath = this.reflector.getAllAndOverride(contract_scoped_decorator_1.CONTRACT_SCOPED_KEY, [
53
+ context.getHandler(),
54
+ context.getClass(),
55
+ ]);
56
+ const isContractScoped = contractScopedPath !== undefined;
57
+ if (!isContractScoped &&
58
+ (!requiredRoles || requiredRoles.length === 0) &&
50
59
  (!requiredPermissions || requiredPermissions.length === 0)) {
51
60
  return true;
52
61
  }
@@ -56,6 +65,11 @@ let AuthorizationGuard = AuthorizationGuard_1 = class AuthorizationGuard {
56
65
  this.logger.warn('No user found in request context for authorization');
57
66
  throw new common_1.ForbiddenException('Authentication required for access');
58
67
  }
68
+ // [Permisos por contrato] Binding síncrono: el contrato de la request debe coincidir
69
+ // con el contrato activo del token. Roles de sistema/globales (super_admin / system): bypass.
70
+ if (isContractScoped && !this.isGlobalBypass(user)) {
71
+ this.assertContractBinding(user, request, contractScopedPath ?? '');
72
+ }
59
73
  const userId = user.sub;
60
74
  const userRoles = user.role || [];
61
75
  // Dos conjuntos resueltos en la carga del JWT: permissions = acceso pleno;
@@ -142,6 +156,54 @@ let AuthorizationGuard = AuthorizationGuard_1 = class AuthorizationGuard {
142
156
  }
143
157
  return !READ_METHODS.has((method ?? '').toUpperCase());
144
158
  }
159
+ /**
160
+ * [Permisos por contrato] Verifica que el contrato sobre el que opera la petición
161
+ * coincida con el `currentContractId` del token. Lanza ForbiddenException si no hay
162
+ * contrato activo, no se puede resolver el contrato de la request, o no coinciden.
163
+ */
164
+ assertContractBinding(user, request, path) {
165
+ const tokenContract = typeof user.currentContractId === 'string' ? user.currentContractId : undefined;
166
+ if (!tokenContract) {
167
+ this.logger.warn(`Contract-scoped access denied: user ${user.sub} has no active contract in token`);
168
+ throw new common_1.ForbiddenException('No active contract selected. Select a contract first.');
169
+ }
170
+ const reqContract = this.extractContractId(request, path);
171
+ if (!reqContract) {
172
+ this.logger.warn(`Contract-scoped access denied: could not resolve contract id from request (path='${path}')`);
173
+ throw new common_1.ForbiddenException('Could not resolve contract id from request');
174
+ }
175
+ if (reqContract !== tokenContract) {
176
+ this.logger.warn(`Contract-scoped access denied: token scoped to ${tokenContract} but request targets ${reqContract}`);
177
+ throw new common_1.ForbiddenException('Token is not scoped to the requested contract');
178
+ }
179
+ }
180
+ /** Roles de sistema/globales que pueden operar sin contrato activo (bypass del binding). */
181
+ isGlobalBypass(user) {
182
+ if (user.tenantContext === 'system') {
183
+ return true;
184
+ }
185
+ const roles = (user.role || []);
186
+ return roles.includes(contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN);
187
+ }
188
+ /**
189
+ * Extrae el contractId de la request. `path` en formato '<fuente>.<campo>'
190
+ * (params/body/query). Si está vacío, prueba ubicaciones comunes en orden:
191
+ * params.contractId → params.id → body.contractId → query.contractId.
192
+ */
193
+ extractContractId(request, path) {
194
+ const candidates = path
195
+ ? [path]
196
+ : ['params.contractId', 'params.id', 'body.contractId', 'query.contractId'];
197
+ const bags = request;
198
+ for (const candidate of candidates) {
199
+ const [source, key] = candidate.split('.');
200
+ const value = source && key ? bags[source]?.[key] : undefined;
201
+ if (typeof value === 'string' && value.length > 0) {
202
+ return value;
203
+ }
204
+ }
205
+ return undefined;
206
+ }
145
207
  };
146
208
  exports.AuthorizationGuard = AuthorizationGuard;
147
209
  exports.AuthorizationGuard = AuthorizationGuard = AuthorizationGuard_1 = __decorate([
@@ -35,6 +35,15 @@ export interface JwtPayload {
35
35
  * no se afectan. El AuthorizationGuard usa este conjunto para bloquear escrituras.
36
36
  */
37
37
  permissionsView?: string[];
38
+ /**
39
+ * [Permisos por contrato] Contrato activo que el usuario seleccionó en Auth. Cuando
40
+ * está presente, `role`/`permissions`/`permissionsView` reflejan el rol del usuario
41
+ * EN ese contrato. Ausente ⇒ modo global (retrocompatible). El AuthorizationGuard usa
42
+ * este valor para el binding de los endpoints marcados con `@ContractScoped`.
43
+ */
44
+ currentContractId?: string;
45
+ /** [Permisos por contrato] Código del rol del usuario en `currentContractId`. */
46
+ currentContractRoleCode?: string;
38
47
  /** User's full name */
39
48
  fullName: string;
40
49
  /** User's email */
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-payload.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/jwt-payload.interface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,cAAc;IACd,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,gCAAgC;IAChC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,sDAAsD;IACtD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,aAAa,CAAC,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IACjD,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mBAAmB;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,wFAAwF;IACxF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAqB,SAAQ,OAAO;IACnD,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,wBAAwB;IACxB,GAAG,EAAE,aAAa,CAAC;IACnB,kCAAkC;IAClC,MAAM,CAAC,EAAE;QACP,0CAA0C;QAC1C,gBAAgB,CAAC,EAAE,OAAO,CAAC;QAC3B,iCAAiC;QACjC,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,uCAAuC;QACvC,uBAAuB,CAAC,EAAE,OAAO,CAAC;KACnC,CAAC;IACF,6BAA6B;IAC7B,QAAQ,CAAC,EAAE;QACT,6BAA6B;QAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,2BAA2B;QAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;QAC1B,wCAAwC;QACxC,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,kCAAkC;QAClC,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,gCAAgC;IAChC,WAAW,CAAC,EAAE;QACZ,4CAA4C;QAC5C,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,gCAAgC;QAChC,QAAQ,CAAC,EAAE,UAAU,CAAC;KACvB,CAAC;CACH"}
1
+ {"version":3,"file":"jwt-payload.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/jwt-payload.interface.ts"],"names":[],"mappings":"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"}
@@ -89,7 +89,7 @@ let ContractXAuthorizationService = class ContractXAuthorizationService {
89
89
  * Check if user has system-level access
90
90
  */
91
91
  hasSystemLevelAccess(userRoles) {
92
- return userRoles.some(role => role === contractx_roles_constants_1.CONTRACTX_ROLES.SUPERADMIN ||
92
+ return userRoles.some(role => role === contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN ||
93
93
  role === contractx_roles_constants_1.CONTRACTX_ROLES.SUPPORT ||
94
94
  (0, contractx_roles_constants_1.isSystemRole)(role));
95
95
  }
@@ -325,14 +325,14 @@ let ContractXAuthorizationService = class ContractXAuthorizationService {
325
325
  contracts: {
326
326
  create: [contractx_roles_constants_1.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN],
327
327
  delete: [contractx_roles_constants_1.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN],
328
- admin: [contractx_roles_constants_1.CONTRACTX_ROLES.SUPERADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.SUPPORT],
328
+ admin: [contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.SUPPORT],
329
329
  },
330
330
  projects: {
331
331
  create: [contractx_roles_constants_1.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN],
332
332
  delete: [contractx_roles_constants_1.CONTRACTX_ROLES.CLIENT_CONTRACT_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.PROVIDER_CONTRACT_ADMIN],
333
333
  },
334
334
  security_control: {
335
- '*': [contractx_roles_constants_1.CONTRACTX_ROLES.SUPERADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.SUPPORT],
335
+ '*': [contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN, contractx_roles_constants_1.CONTRACTX_ROLES.SUPPORT],
336
336
  },
337
337
  };
338
338
  return resourceRoleMap[resource]?.[action] || resourceRoleMap[resource]?.['*'] || [];
@@ -272,7 +272,7 @@ let UserContextService = class UserContextService {
272
272
  * Check if user is a superadmin
273
273
  */
274
274
  isSuperAdmin() {
275
- return this.hasRole(contractx_roles_constants_1.CONTRACTX_ROLES.SUPERADMIN);
275
+ return this.hasRole(contractx_roles_constants_1.CONTRACTX_ROLES.SUPER_ADMIN);
276
276
  }
277
277
  /**
278
278
  * Check if user has admin privileges (superadmin or contract admin)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "permissions-contractx",
3
- "version": "1.6.0",
3
+ "version": "2.0.0",
4
4
  "description": "Enterprise-grade authentication and authorization package for NestJS microservices with role-based and permission-based access control",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",