soajs.controller 4.2.42 → 4.2.43

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.
Files changed (37) hide show
  1. package/.github/workflows/ci.yml +43 -0
  2. package/.github/workflows/release.yml +92 -0
  3. package/ARCHITECTURE.md +193 -0
  4. package/Gruntfile.js +1 -1
  5. package/docs/configuration-custom-registry.md +421 -0
  6. package/docs/configuration-services-config.md +275 -0
  7. package/docs/data-flow.md +138 -0
  8. package/docs/deployment.md +205 -0
  9. package/docs/external-integrations.md +159 -0
  10. package/docs/gateway-routes.md +259 -0
  11. package/docs/maintenance-routes.md +308 -0
  12. package/docs/middleware/awareness.md +120 -0
  13. package/docs/middleware/cors.md +88 -0
  14. package/docs/middleware/enhancer.md +75 -0
  15. package/docs/middleware/favicon.md +36 -0
  16. package/docs/middleware/gotoService.md +146 -0
  17. package/docs/middleware/ip2ban.md +70 -0
  18. package/docs/middleware/key.md +196 -0
  19. package/docs/middleware/keyACL.md +139 -0
  20. package/docs/middleware/lastSeen.md +111 -0
  21. package/docs/middleware/maintenanceMode.md +81 -0
  22. package/docs/middleware/mt.md +188 -0
  23. package/docs/middleware/oauth.md +173 -0
  24. package/docs/middleware/response.md +106 -0
  25. package/docs/middleware/soajs.md +71 -0
  26. package/docs/middleware/traffic.md +190 -0
  27. package/docs/middleware/url.md +102 -0
  28. package/docs/multi-tenant-security.md +183 -0
  29. package/docs/request-flow.md +230 -0
  30. package/docs/service-discovery.md +167 -0
  31. package/mw/key/index.js +16 -1
  32. package/mw/mt/urac.js +21 -1
  33. package/mw/mt/utils.js +2 -0
  34. package/package.json +7 -7
  35. package/test/unit/mw/key/index.js +150 -0
  36. package/test/unit/mw/mt/urac.js +157 -4
  37. package/.travis.yml +0 -72
@@ -0,0 +1,421 @@
1
+ # Custom Registry Configuration
2
+
3
+ Environment-specific gateway settings stored in the Core DB custom registry.
4
+
5
+ ## Configuration Structure Overview
6
+
7
+ These settings are accessed via `registry.custom.gateway.value.*` and `registry.custom.oauth.value.*`.
8
+
9
+ ```
10
+ registry.custom
11
+ ├── gateway
12
+ │ └── value
13
+ │ ├── mt
14
+ │ │ └── whitelist # IP whitelist for bypassing security
15
+ │ ├── traffic
16
+ │ │ ├── model # Throttling storage backend
17
+ │ │ ├── ip2ban # Banned IP addresses
18
+ │ │ └── throttling # Service-level rate limiting
19
+ │ ├── maintenanceMode # Gateway maintenance mode
20
+ │ ├── lastSeen # User activity tracking
21
+ │ └── gotoService
22
+ │ ├── monitor # Request monitoring config
23
+ │ └── renewReqMonitorOff # Disable timeout renewal
24
+ └── oauth
25
+ └── value
26
+ ├── roaming # Cross-environment access
27
+ ├── pinWrapper # PIN-based login endpoint
28
+ └── pinWhitelist # PIN login API whitelist
29
+ ```
30
+
31
+ ---
32
+
33
+ ## 1. Maintenance Mode
34
+
35
+ **Path:** `registry.custom.gateway.value.maintenanceMode`
36
+
37
+ **Middleware:** `mw/maintenanceMode/index.js`
38
+
39
+ Enables gateway-wide maintenance mode, returning a configurable status to all requests.
40
+
41
+ ```javascript
42
+ {
43
+ "maintenanceMode": {
44
+ "on": true, // Enable maintenance mode
45
+ "status": 503, // HTTP status code (default: 503)
46
+ "message": "Maintenance in progress", // Custom message
47
+ "retryAfter": 3600 // Retry-After header in seconds
48
+ }
49
+ }
50
+ ```
51
+
52
+ | Field | Type | Default | Description |
53
+ |-------|------|---------|-------------|
54
+ | `on` | boolean | `false` | Enable/disable maintenance mode |
55
+ | `status` | number | `503` | HTTP status code to return |
56
+ | `message` | string | `"Maintenance mode is on, come back soon"` | Response message |
57
+ | `retryAfter` | number | - | Seconds until retry (sets `Retry-After` header) |
58
+
59
+ ---
60
+
61
+ ## 2. IP Blacklist (IP2Ban)
62
+
63
+ **Path:** `registry.custom.gateway.value.traffic.ip2ban`
64
+
65
+ **Middleware:** `mw/ip2ban/index.js`
66
+
67
+ Blocks specified IP addresses from accessing the gateway entirely.
68
+
69
+ ```javascript
70
+ {
71
+ "traffic": {
72
+ "ip2ban": ["192.168.1.100", "10.0.0.50", "::1"]
73
+ }
74
+ }
75
+ ```
76
+
77
+ | Field | Type | Default | Description |
78
+ |-------|------|---------|-------------|
79
+ | `ip2ban` | string[] | `[]` | Array of IP addresses to block (returns 403) |
80
+
81
+ ---
82
+
83
+ ## 3. Rate Limiting (Throttling)
84
+
85
+ **Path:** `registry.custom.gateway.value.traffic`
86
+
87
+ **Middleware:** `mw/traffic/index.js`
88
+
89
+ Configures rate limiting strategies and storage backend.
90
+
91
+ ```javascript
92
+ {
93
+ "traffic": {
94
+ "model": "mongo", // Storage: "memory" or "mongo"
95
+ "throttling": {
96
+ "oauth": { // Service-specific config
97
+ "publicAPIStrategy": "default", // Strategy for public APIs
98
+ "privateAPIStrategy": "heavy", // Strategy for authenticated APIs
99
+ "apis": ["/token", "/authorization"] // Specific APIs to throttle
100
+ },
101
+ "payment": {
102
+ "publicAPIStrategy": "strict",
103
+ "apis": ["/charge", "/refund"]
104
+ }
105
+ }
106
+ }
107
+ }
108
+ ```
109
+
110
+ | Field | Type | Default | Description |
111
+ |-------|------|---------|-------------|
112
+ | `model` | string | `"memory"` | Storage backend: `"memory"` or `"mongo"` |
113
+ | `throttling` | object | `{}` | Service-level throttling overrides |
114
+ | `throttling[service].publicAPIStrategy` | string | - | Strategy name for unauthenticated requests |
115
+ | `throttling[service].privateAPIStrategy` | string | - | Strategy name for authenticated requests |
116
+ | `throttling[service].apis` | string[] | - | Specific API paths to apply throttling |
117
+
118
+ **Configuration Cascade (highest to lowest priority):**
119
+ 1. Tenant service config: `keyObj.config.gateway.throttling`
120
+ 2. Custom registry: `registry.custom.gateway.value.traffic.throttling`
121
+ 3. Global default: `registry.serviceConfig.throttling`
122
+
123
+ ---
124
+
125
+ ## 4. Multi-Tenant IP Whitelist
126
+
127
+ **Path:** `registry.custom.gateway.value.mt.whitelist`
128
+
129
+ **Middleware:** `mw/mt/utils.js`
130
+
131
+ Allows specific IP ranges to bypass ACL and/or OAuth checks.
132
+
133
+ ```javascript
134
+ {
135
+ "mt": {
136
+ "whitelist": {
137
+ "ips": ["10.0.0.0/8", "192.168.1.0/24", "172.16.0.0/12"],
138
+ "acl": true, // Skip ACL checks for whitelisted IPs
139
+ "oauth": true // Skip OAuth checks for whitelisted IPs
140
+ }
141
+ }
142
+ }
143
+ ```
144
+
145
+ | Field | Type | Default | Description |
146
+ |-------|------|---------|-------------|
147
+ | `ips` | string[] | `[]` | IP addresses/CIDR ranges to whitelist |
148
+ | `acl` | boolean | `false` | Skip ACL validation for whitelisted IPs |
149
+ | `oauth` | boolean | `false` | Skip OAuth validation for whitelisted IPs |
150
+
151
+ ---
152
+
153
+ ## 5. User Activity Tracking (Last Seen)
154
+
155
+ **Path:** `registry.custom.gateway.value.lastSeen`
156
+
157
+ **Middleware:** `mw/lastSeen/index.js`
158
+
159
+ Tracks user activity by notifying a service (typically URAC) of user access.
160
+
161
+ ```javascript
162
+ {
163
+ "lastSeen": {
164
+ "active": true, // Enable tracking
165
+ "serviceName": "urac", // Service to notify
166
+ "serviceVersion": "3", // Service version
167
+ "api": "/user/last/seen", // API endpoint
168
+ "network": "internal" // Optional network identifier
169
+ }
170
+ }
171
+ ```
172
+
173
+ | Field | Type | Default | Description |
174
+ |-------|------|---------|-------------|
175
+ | `active` | boolean | `false` | Enable/disable activity tracking |
176
+ | `serviceName` | string | `"urac"` | Service to receive notifications |
177
+ | `serviceVersion` | string | `"3"` | Version of the service |
178
+ | `api` | string | `"/user/last/seen"` | API endpoint to call |
179
+ | `network` | string | - | Optional network info sent in request body |
180
+
181
+ ---
182
+
183
+ ## 6. Request Monitoring
184
+
185
+ **Path:** `registry.custom.gateway.value.gotoService.monitor`
186
+
187
+ **Middleware:** `mw/gotoService/redirectToService.js`
188
+
189
+ Controls which services are monitored for metrics collection.
190
+
191
+ ```javascript
192
+ {
193
+ "gotoService": {
194
+ "monitor": {
195
+ "blacklist": ["oauth", "urac", "soamonitor"], // Services to NOT monitor
196
+ "whitelist": ["payment", "orders", "users"] // Services to monitor (exclusive)
197
+ }
198
+ }
199
+ }
200
+ ```
201
+
202
+ | Field | Type | Default | Description |
203
+ |-------|------|---------|-------------|
204
+ | `blacklist` | string[] | `[]` | Services to exclude from monitoring |
205
+ | `whitelist` | string[] | `[]` | If set, ONLY these services are monitored |
206
+
207
+ **Note:** If `whitelist` is defined, only services in the whitelist are monitored. Otherwise, all services except those in the blacklist are monitored.
208
+
209
+ ---
210
+
211
+ ## 7. Request Timeout Renewal
212
+
213
+ **Path:** `registry.custom.gateway.value.gotoService.renewReqMonitorOff`
214
+
215
+ **Middleware:** `mw/gotoService/lib/preRedirect.js`
216
+
217
+ Disables the heartbeat renewal mechanism for long-running requests.
218
+
219
+ ```javascript
220
+ {
221
+ "gotoService": {
222
+ "renewReqMonitorOff": true // Disable timeout renewal
223
+ }
224
+ }
225
+ ```
226
+
227
+ | Field | Type | Default | Description |
228
+ |-------|------|---------|-------------|
229
+ | `renewReqMonitorOff` | boolean | `false` | Disable request timeout renewal mechanism |
230
+
231
+ ---
232
+
233
+ ## 8. OAuth Roaming (Cross-Environment)
234
+
235
+ **Path:** `registry.custom.oauth.value.roaming`
236
+
237
+ **Middleware:** `mw/gotoService/roaming.js`
238
+
239
+ Enables cross-environment access for specific services with IP-based whitelisting.
240
+
241
+ ```javascript
242
+ {
243
+ "roaming": {
244
+ "services": {
245
+ "oauth": {
246
+ "whitelistips": ["192.144.3.1", "10.0.0.1"]
247
+ },
248
+ "payment": {
249
+ "whitelistips": ["127.0.0.1", "192.168.1.0/24"]
250
+ }
251
+ }
252
+ }
253
+ }
254
+ ```
255
+
256
+ | Field | Type | Default | Description |
257
+ |-------|------|---------|-------------|
258
+ | `services` | object | `{}` | Service-specific roaming configuration |
259
+ | `services[name].whitelistips` | string[] | `[]` | IPs allowed to roam to this service |
260
+
261
+ ---
262
+
263
+ ## 9. PIN Login Wrapper
264
+
265
+ **Path:** `registry.custom.oauth.value.pinWrapper`
266
+
267
+ **Middleware:** `mw/mt/utils.js`
268
+
269
+ Defines a custom PIN-based login endpoint that bypasses standard OAuth flow.
270
+
271
+ ```javascript
272
+ {
273
+ "pinWrapper": {
274
+ "servicename": "auth-service", // Service providing PIN login
275
+ "apiname": "/pin/login" // API endpoint for PIN login
276
+ }
277
+ }
278
+ ```
279
+
280
+ | Field | Type | Default | Description |
281
+ |-------|------|---------|-------------|
282
+ | `servicename` | string | - | Service name providing PIN authentication |
283
+ | `apiname` | string | - | API endpoint path for PIN login |
284
+
285
+ ---
286
+
287
+ ## 10. PIN Login API Whitelist
288
+
289
+ **Path:** `registry.custom.oauth.value.pinWhitelist`
290
+
291
+ **Middleware:** `mw/mt/utils.js`
292
+
293
+ Whitelists specific APIs that can be accessed when a user is PIN-locked (during PIN login flow).
294
+
295
+ ```javascript
296
+ {
297
+ "pinWhitelist": {
298
+ "auth-service": {
299
+ "get": {
300
+ "apis": ["/pin/verify", "/pin/status"],
301
+ "regex": ["/api/v[0-9]+/pin/.*"]
302
+ },
303
+ "post": {
304
+ "apis": ["/pin/login", "/pin/reset"],
305
+ "regex": []
306
+ }
307
+ },
308
+ "user-service": {
309
+ "get": {
310
+ "apis": ["/user/minimal"],
311
+ "regex": []
312
+ }
313
+ }
314
+ }
315
+ }
316
+ ```
317
+
318
+ | Field | Type | Default | Description |
319
+ |-------|------|---------|-------------|
320
+ | `[service]` | object | - | Service-specific PIN whitelist |
321
+ | `[service].[method].apis` | string[] | `[]` | Exact API paths to whitelist |
322
+ | `[service].[method].regex` | string[] | `[]` | Regex patterns for matching APIs |
323
+
324
+ ---
325
+
326
+ ## Complete Configuration Example
327
+
328
+ ```javascript
329
+ // Core DB: custom_registry collection
330
+ {
331
+ "_id": ObjectId("..."),
332
+ "name": "gateway",
333
+ "value": {
334
+ "maintenanceMode": {
335
+ "on": false,
336
+ "status": 503,
337
+ "message": "System maintenance in progress",
338
+ "retryAfter": 1800
339
+ },
340
+ "mt": {
341
+ "whitelist": {
342
+ "ips": ["10.0.0.0/8"],
343
+ "acl": true,
344
+ "oauth": false
345
+ }
346
+ },
347
+ "traffic": {
348
+ "model": "mongo",
349
+ "ip2ban": ["192.168.1.100"],
350
+ "throttling": {
351
+ "oauth": {
352
+ "publicAPIStrategy": "default",
353
+ "apis": ["/token"]
354
+ },
355
+ "payment": {
356
+ "publicAPIStrategy": "strict",
357
+ "privateAPIStrategy": "heavy",
358
+ "apis": ["/charge", "/refund", "/subscribe"]
359
+ }
360
+ }
361
+ },
362
+ "lastSeen": {
363
+ "active": true,
364
+ "serviceName": "urac",
365
+ "serviceVersion": "3",
366
+ "api": "/user/last/seen",
367
+ "network": "production"
368
+ },
369
+ "gotoService": {
370
+ "monitor": {
371
+ "blacklist": ["soamonitor", "urac"]
372
+ },
373
+ "renewReqMonitorOff": false
374
+ }
375
+ }
376
+ }
377
+
378
+ // Separate OAuth custom registry entry
379
+ {
380
+ "_id": ObjectId("..."),
381
+ "name": "oauth",
382
+ "value": {
383
+ "roaming": {
384
+ "services": {
385
+ "oauth": {
386
+ "whitelistips": ["192.144.3.1"]
387
+ }
388
+ }
389
+ },
390
+ "pinWrapper": {
391
+ "servicename": "auth",
392
+ "apiname": "/pin/login"
393
+ },
394
+ "pinWhitelist": {
395
+ "auth": {
396
+ "post": {
397
+ "apis": ["/pin/login", "/pin/verify"],
398
+ "regex": []
399
+ }
400
+ }
401
+ }
402
+ }
403
+ }
404
+ ```
405
+
406
+ ---
407
+
408
+ ## Middleware Processing Order
409
+
410
+ Custom registry configurations are processed in this order:
411
+
412
+ | Order | Middleware | Configuration Used |
413
+ |-------|------------|-------------------|
414
+ | 1 | ip2ban | `traffic.ip2ban` |
415
+ | 2 | maintenanceMode | `maintenanceMode` |
416
+ | 3 | gotoService/roaming | `oauth.value.roaming` |
417
+ | 4 | gotoService/preRedirect | `gotoService.renewReqMonitorOff` |
418
+ | 5 | gotoService/redirectToService | `gotoService.monitor` |
419
+ | 6 | mt (security checks) | `mt.whitelist`, `oauth.value.pinWrapper`, `oauth.value.pinWhitelist` |
420
+ | 7 | traffic | `traffic.model`, `traffic.throttling` |
421
+ | 8 | lastSeen | `lastSeen` |
@@ -0,0 +1,275 @@
1
+ # Services Config (Tenant Key Configuration)
2
+
3
+ Tenant key-specific configuration stored in `keyObj.config`. These settings are specific to each tenant's external key and override environment-level settings.
4
+
5
+ ## Configuration Structure Overview
6
+
7
+ ```
8
+ keyObj.config
9
+ ├── gateway
10
+ │ ├── networkPackages # Network-based package override
11
+ │ ├── validateTokenAccount # Token account validation
12
+ │ └── throttling # Tenant-specific throttling
13
+ └── [serviceName] # Service URL override
14
+ ├── url # Single URL for all versions
15
+ └── urls # Version-specific URLs
16
+ ```
17
+
18
+ ---
19
+
20
+ ## 1. Network Package Override
21
+
22
+ **Path:** `keyObj.config.gateway.networkPackages`
23
+
24
+ **Middlewares:**
25
+ - `mw/key/index.js` (default package)
26
+ - `mw/mt/urac.js` (user packages)
27
+
28
+ Allows different packages to be loaded based on the network identifier configured in the custom registry.
29
+
30
+ ```javascript
31
+ {
32
+ "gateway": {
33
+ "networkPackages": {
34
+ "mw": { // Network identifier (from lastSeen.network)
35
+ "AVAPP": { // Product code (keyObj.application.product)
36
+ "default": "AVAPP_DEFAU", // Default package to use for this network
37
+ "users": { // User-specific package mappings
38
+ "AVAPP_EXMPL": "AVAPP_ALTRN" // Map user's package to alternate
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### How it Works
48
+
49
+ The network package override operates at two levels:
50
+
51
+ **1. Key Middleware** (`mw/key/index.js`) - Applies `default` package override for all requests
52
+
53
+ ```
54
+ 1. Get network from registry
55
+ network = registry.custom.gateway.value.lastSeen.network (e.g., "mw")
56
+
57
+ 2. Get product from keyObj
58
+ product = keyObj.application.product (e.g., "AVAPP")
59
+
60
+ 3. Check for network package config
61
+ config = keyObj.config.gateway.networkPackages[network][product]
62
+
63
+ 4. If config.default exists:
64
+ ├── Original: keyObj.application.package = "AVAPP_EXMPL"
65
+ ├── Override: keyObj.application.package = "AVAPP_DEFAU"
66
+ └── Log: "Network package override: replaced package [AVAPP_EXMPL]
67
+ with [AVAPP_DEFAU] for network [mw] and product [AVAPP]"
68
+
69
+ 5. Continue to load the (possibly overridden) package
70
+ ```
71
+
72
+ **2. MT Middleware** (`mw/mt/urac.js`) - Applies `users` package override for authenticated user's allowed packages
73
+
74
+ ```
75
+ In resolveACL() before calling getPackagesData():
76
+
77
+ 1. Get network from registry
78
+ network = registry.custom.gateway.value.lastSeen.network (e.g., "mw")
79
+
80
+ 2. Get product from soajs.tenant.application.product (e.g., "AVAPP")
81
+
82
+ 3. Get user's allowed packages
83
+ allowedPackages = userRecord.groupsConfig.allowedPackages[product]
84
+ (e.g., ["AVAPP_EXMPL"])
85
+
86
+ 4. Check for network package config
87
+ config = keyObj.config.gateway.networkPackages[network][product]
88
+
89
+ 5. If config.users exists, for each package in allowedPackages:
90
+ ├── Check: config.users["AVAPP_EXMPL"] = "AVAPP_ALTRN"
91
+ ├── Replace: allowedPackages[i] = "AVAPP_ALTRN"
92
+ └── Log: "User network package override: replaced package [AVAPP_EXMPL]
93
+ with [AVAPP_ALTRN] for network [mw] and product [AVAPP]"
94
+
95
+ 6. Call getPackagesData() with the (possibly modified) allowedPackages
96
+ ```
97
+
98
+ | Field | Type | Description |
99
+ |-------|------|-------------|
100
+ | `networkPackages` | object | Top-level container for network-based package configs |
101
+ | `networkPackages[network]` | object | Config for a specific network (e.g., "mw") |
102
+ | `networkPackages[network][product]` | object | Config for a specific product |
103
+ | `networkPackages[network][product].default` | string | Default package for key middleware (tenant-level) |
104
+ | `networkPackages[network][product].users` | object | User-specific package mappings for mt middleware |
105
+ | `networkPackages[network][product].users[packageCode]` | string | Replacement package for this user's package |
106
+
107
+ ---
108
+
109
+ ## 2. Validate Token Account
110
+
111
+ **Path:** `keyObj.config.gateway.validateTokenAccount`
112
+
113
+ **Middleware:** `mw/mt/utils.js` → `uracCheck()`
114
+
115
+ Forces users to re-login when their email or phone changes, providing additional security for sensitive account changes.
116
+
117
+ ```javascript
118
+ {
119
+ "gateway": {
120
+ "validateTokenAccount": {
121
+ "email": true, // Validate email hasn't changed
122
+ "phone": true // Validate phone hasn't changed
123
+ }
124
+ }
125
+ }
126
+ ```
127
+
128
+ ### How it Works
129
+
130
+ - When a user's OAuth token is validated, the middleware compares the current user profile with the token's stored user data
131
+ - If `email: true` and the user's email has changed since token creation → Error 146 (invalid token)
132
+ - If `phone: true` and the user's phone has changed since token creation → Error 146 (invalid token)
133
+ - This forces users to re-authenticate after changing sensitive account information
134
+
135
+ | Field | Type | Default | Description |
136
+ |-------|------|---------|-------------|
137
+ | `validateTokenAccount.email` | boolean | `false` | Invalidate token if email changed |
138
+ | `validateTokenAccount.phone` | boolean | `false` | Invalidate token if phone changed |
139
+
140
+ ---
141
+
142
+ ## 3. Tenant-Specific Throttling
143
+
144
+ **Path:** `keyObj.config.gateway.throttling`
145
+
146
+ **Middleware:** `mw/traffic/index.js`
147
+
148
+ Allows overriding the global throttling configuration at the tenant level.
149
+
150
+ ```javascript
151
+ {
152
+ "gateway": {
153
+ "throttling": {
154
+ "serviceName": { // Service to apply throttling to
155
+ "publicAPIStrategy": "default", // Strategy for unauthenticated requests
156
+ "privateAPIStrategy": "heavy", // Strategy for authenticated requests
157
+ "apis": ["/api1", "/api2"] // Optional: specific APIs (if omitted, applies to all)
158
+ }
159
+ }
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### Configuration Cascade
165
+
166
+ Throttling configuration is resolved in this order (highest to lowest priority):
167
+
168
+ 1. `keyObj.config.gateway.throttling` (tenant service config)
169
+ 2. `registry.custom.gateway.value.traffic.throttling` (custom registry)
170
+ 3. `registry.serviceConfig.throttling` (global default)
171
+
172
+ | Field | Type | Description |
173
+ |-------|------|-------------|
174
+ | `throttling[service]` | object | Throttling config for a specific service |
175
+ | `throttling[service].publicAPIStrategy` | string | Strategy name for unauthenticated requests |
176
+ | `throttling[service].privateAPIStrategy` | string | Strategy name for authenticated requests |
177
+ | `throttling[service].apis` | string[] | Optional: specific APIs to throttle (all if omitted) |
178
+
179
+ ---
180
+
181
+ ## 4. Service URL Override
182
+
183
+ **Path:** `keyObj.config[serviceName]`
184
+
185
+ **Middleware:** `mw/gotoService/lib/preRedirect.js`
186
+
187
+ Allows tenants to override the URL for specific services, useful for pointing to custom endpoints or different service versions.
188
+
189
+ ```javascript
190
+ {
191
+ "urac": { // Service name
192
+ "url": "https://custom-urac.example.com" // Custom URL (overrides registry)
193
+ },
194
+ "oauth": { // Another service
195
+ "urls": [ // Versioned URLs
196
+ { "version": "1", "url": "https://oauth-v1.example.com" },
197
+ { "version": "2", "url": "https://oauth-v2.example.com" }
198
+ ]
199
+ }
200
+ }
201
+ ```
202
+
203
+ ### How it Works
204
+
205
+ - For endpoint-type services, the gateway checks `keyObj.config[serviceName]`
206
+ - If `url` exists, it overrides the registry URL
207
+ - If `urls` array exists and matches the requested version, that versioned URL is used
208
+ - This allows per-tenant service routing without modifying the global registry
209
+
210
+ | Field | Type | Description |
211
+ |-------|------|-------------|
212
+ | `config[service].url` | string | Custom URL for all versions of this service |
213
+ | `config[service].urls` | array | Array of version-specific URLs |
214
+ | `config[service].urls[].version` | string | Service version |
215
+ | `config[service].urls[].url` | string | URL for this specific version |
216
+
217
+ ---
218
+
219
+ ## Complete Configuration Example
220
+
221
+ ```javascript
222
+ // In tenant key configuration (keyObj.config)
223
+ {
224
+ "gateway": {
225
+ "networkPackages": {
226
+ "mw": {
227
+ "AVAPP": {
228
+ "default": "AVAPP_DEFAU",
229
+ "users": {
230
+ "AVAPP_EXMPL": "AVAPP_ALTRN",
231
+ "AVAPP_BASIC": "AVAPP_BASIC_MW"
232
+ }
233
+ }
234
+ },
235
+ "partner": {
236
+ "AVAPP": {
237
+ "default": "AVAPP_PARTNER",
238
+ "users": {}
239
+ }
240
+ }
241
+ },
242
+ "validateTokenAccount": {
243
+ "email": true,
244
+ "phone": false
245
+ },
246
+ "throttling": {
247
+ "payment": {
248
+ "publicAPIStrategy": "strict",
249
+ "privateAPIStrategy": "premium",
250
+ "apis": ["/charge", "/refund"]
251
+ }
252
+ }
253
+ },
254
+ "urac": {
255
+ "url": "https://custom-urac.tenant.com"
256
+ },
257
+ "oauth": {
258
+ "urls": [
259
+ { "version": "1", "url": "https://oauth-v1.tenant.com" },
260
+ { "version": "2", "url": "https://oauth-v2.tenant.com" }
261
+ ]
262
+ }
263
+ }
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Error Codes
269
+
270
+ | Code | Description |
271
+ |------|-------------|
272
+ | 144 | External key is not valid for this environment |
273
+ | 146 | Invalid token (account validation failed - email/phone changed) |
274
+ | 148 | External key is invalid or has been disabled |
275
+ | 149 | Product package not found |