@ti-engine/core 1.3.13 → 1.6.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/CHANGELOG.md +70 -1
- package/README.md +3 -3
- package/bin/localization/labels.json +9 -0
- package/bin/settings.json +1 -1
- package/components/auditing.js +1 -18
- package/components/connection-observer.js +2 -2
- package/components/definitions.types.js +248 -0
- package/components/exchange/message-dispatcher.js +1 -1
- package/components/exchange/message-exchange.js +6 -30
- package/components/exchange/message-handler.js +16 -6
- package/components/exchange/message-memory-cache.js +1 -1
- package/components/exchange/message-observer.js +2 -2
- package/components/exchange/message-receiver.js +4 -3
- package/components/exchange/message-sender.js +2 -2
- package/components/exchange/message-tracer.js +4 -27
- package/components/service-caller.js +1 -40
- package/components/service-consumer.js +1 -1
- package/components/service-executor.js +1 -16
- package/components/service-instance.js +4 -9
- package/components/service-provider.js +9 -8
- package/integrations/redis-integration.js +8 -13
- package/package.json +10 -11
- package/utils/cache.js +64 -18
- package/utils/config.js +4 -101
- package/utils/exceptions.js +37 -20
- package/utils/localization.js +2 -17
- package/utils/logger.js +5 -8
- package/utils/tools.js +25 -20
- package/integrations/gcloud-integration.js +0 -65
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
# ti-engine changelog
|
|
2
2
|
|
|
3
|
-
This document
|
|
3
|
+
This document contains the list of changes made to the framework. The format is based on the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
|
|
4
|
+
|
|
5
|
+
## Version 1.6.0
|
|
6
|
+
|
|
7
|
+
* refactor(exchange)!: replace the blake2 keyed hash with native `node:crypto` HMAC-SHA256 in the message integrity check
|
|
8
|
+
* build(deps)!: remove the `blake2` native addon dependency (no longer builds on Node 26; replaced by the built-in `node:crypto`)
|
|
9
|
+
* fix(exchange): use a constant-time comparison for the message security hash
|
|
10
|
+
* fix(exchange): ship an empty default `securityHashKey` and warn (once) when the security hash is enabled with a missing/default key
|
|
11
|
+
* test(exchange): add the first core test suite — message-hash determinism, tamper detection, and the constant-time comparison
|
|
12
|
+
|
|
13
|
+
> **BREAKING (wire):** the message security hash changes from keyed-BLAKE2b (128 hex) to HMAC-SHA256 (64 hex). Old and new core versions produce mutually incompatible hashes. When upgrading across this version with `securityHashEnabled=true`, redeploy all services together — recommended order: set `securityHashEnabled=false` everywhere → deploy the new core to all services → re-enable. HMAC also accepts keys of any length (custom keys >64 bytes that previously failed under blake2b now work). The default `securityHashKey` is now empty: set `TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY` in any real deployment, otherwise tamper protection is ineffective.
|
|
14
|
+
|
|
15
|
+
## Version 1.5.1
|
|
16
|
+
|
|
17
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.66.0 to ^1.73.1
|
|
18
|
+
* build(deps): update `ioredis` from ^5.10.1 to ^5.11.1
|
|
19
|
+
|
|
20
|
+
## Version 1.5.0
|
|
21
|
+
|
|
22
|
+
* feat(exceptions): add `E_APP_RESOURCE_ALREADY_EXISTS` (5006) for resource-creation conflicts; intended to be raised with HTTP `409`
|
|
23
|
+
|
|
24
|
+
## Version 1.4.6
|
|
25
|
+
|
|
26
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.65.0 to ^1.66.0
|
|
27
|
+
|
|
28
|
+
## Version 1.4.5
|
|
29
|
+
|
|
30
|
+
* feat(cache): add array-based path support to all `*JSON` methods — passing an array of strings as `path` treats each element as a literal key name using bracket notation, preventing misinterpretation of key names containing dots or other JSONPath special characters
|
|
31
|
+
|
|
32
|
+
## Version 1.4.4
|
|
33
|
+
|
|
34
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.60.0 to ^1.65.0
|
|
35
|
+
|
|
36
|
+
## Version 1.4.3
|
|
37
|
+
|
|
38
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.59.1 to ^1.60.0
|
|
39
|
+
|
|
40
|
+
## Version 1.4.2
|
|
41
|
+
|
|
42
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.55.1 to ^1.59.1
|
|
43
|
+
* build(deps): update `ioredis` from ^5.10.0 to ^5.10.1
|
|
44
|
+
* build(deps): update `lodash` from ^4.17.23 to ^4.18.1
|
|
45
|
+
|
|
46
|
+
## Version 1.4.1
|
|
47
|
+
|
|
48
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.54.1 to ^1.55.1
|
|
49
|
+
|
|
50
|
+
## Version 1.4.0
|
|
51
|
+
|
|
52
|
+
* feat(redis integration): implement support for `JSON.MERGE` and `JSON.MGET` commands
|
|
53
|
+
* feat(cache): add `editJSON` method
|
|
54
|
+
* feat(cache): implement consistent RedisJSON path handling and uniform error wrapping
|
|
55
|
+
* feat(exceptions): add new standardized exception code `E_GEN_NOT_IMPLEMENTED` to use for cases where a feature is not yet implemented
|
|
56
|
+
* feat(exceptions): add new optional, flexible parameter `httpCode` to the `raise` method
|
|
57
|
+
* refactor(exceptions)!: rename the exception class from `Exception` to `TiException` in all referred places
|
|
58
|
+
* refactor(definitions): move all object definitions to a new `definitions.types.js` file
|
|
59
|
+
* refactor(gcloud integration)!: remove file `gcloud-integration.js` and all related functionality (as it was obsolete and a security vulnerability)
|
|
60
|
+
* fix(cache): fix a bug where RedisJSON methods would return `E_GEN_FEATURE_UNSUPPORTED` error while discarding the details of that error
|
|
61
|
+
* fix(config): fix the ENV `TI_LOCALIZATION_LABELS_PATH` to properly support multiple paths to label files
|
|
62
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.52.0 to ^1.54.1
|
|
63
|
+
* build(deps): update `ioredis` from ^5.9.2 to ^5.10.0
|
|
64
|
+
* build(deps)!: remove `@google-cloud/error-reporting`
|
|
65
|
+
|
|
66
|
+
## Version 1.3.14
|
|
67
|
+
|
|
68
|
+
* build(deps): update `@dotenvx/dotenvx` from ^1.51.1 to ^1.52.0
|
|
69
|
+
* build(deps): update `blake2` from ^5.0.0 to ^5.0.1
|
|
70
|
+
* build(deps): update `ioredis` from ^5.8.2 to ^5.9.2
|
|
71
|
+
* build(deps): update `lodash` from ^4.17.21 to ^4.17.23
|
|
72
|
+
* build(engines): update Node.js requirement from >=18.0.0 to >=20.0.0
|
|
4
73
|
|
|
5
74
|
## Version 1.3.13
|
|
6
75
|
|
package/README.md
CHANGED
|
@@ -479,12 +479,12 @@ MESSAGE_EXCHANGE_MESSAGE_STORE (Advanced)
|
|
|
479
479
|
MESSAGE_EXCHANGE_SECURITY_HASH_ENABLED (Advanced)
|
|
480
480
|
: JSON path `messageExchange.securityHashEnabled`, type `boolean`, default `true`
|
|
481
481
|
: ENV variable `TI_MESSAGE_EXCHANGE_SECURITY_HASH_ENABLED`
|
|
482
|
-
: This setting controls whether the message exchange will use a control hash mechanism to ensure there is no tampering with the messages in between service calls. In most cases you would want to keep this enabled since it ensures the integrity of your data. If you are concerned about performance (
|
|
482
|
+
: This setting controls whether the message exchange will use a control hash mechanism to ensure there is no tampering with the messages in between service calls. In most cases you would want to keep this enabled since it ensures the integrity of your data. If you are concerned about performance (the keyed `HMAC-SHA256` hash is rapid, but it still eats some milliseconds) you might want to try and disable this to see if it makes any notable difference.
|
|
483
483
|
|
|
484
484
|
MESSAGE_EXCHANGE_SECURITY_HASH_KEY (Advanced)
|
|
485
|
-
: JSON path `messageExchange.securityHashKey`, type `string`, default `
|
|
485
|
+
: JSON path `messageExchange.securityHashKey`, type `string`, default `empty (must be set)`
|
|
486
486
|
: ENV variable `TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY`
|
|
487
|
-
: This setting holds the
|
|
487
|
+
: This setting holds the HMAC key used by the message exchange control hash mechanism. By default it is empty, which leaves tamper protection ineffective and logs a startup warning. You absolutely must provide your own private key via the ENV variable in any real deployment. Depending on your configuration and infrastructure, it might come from a secure storage, HSM, key vault, etc.
|
|
488
488
|
|
|
489
489
|
MESSAGE_EXCHANGE_TRACE_EXPIRATION_TIME
|
|
490
490
|
: JSON path `messageExchange.traceExpirationTime`, type `number`, default `3600`
|
|
@@ -34,6 +34,9 @@
|
|
|
34
34
|
"1009": {
|
|
35
35
|
"en": "Attempt to override a protected or private method or property detected."
|
|
36
36
|
},
|
|
37
|
+
"1010": {
|
|
38
|
+
"en": "The requested functionality is not yet implemented."
|
|
39
|
+
},
|
|
37
40
|
"2000": {
|
|
38
41
|
"en": "Invalid authorization token provided."
|
|
39
42
|
},
|
|
@@ -108,6 +111,12 @@
|
|
|
108
111
|
},
|
|
109
112
|
"4009": {
|
|
110
113
|
"en": "The request content encoding is not recognized or not supported."
|
|
114
|
+
},
|
|
115
|
+
"5004": {
|
|
116
|
+
"en": "The requested resource cannot be found. See details for more information."
|
|
117
|
+
},
|
|
118
|
+
"5005": {
|
|
119
|
+
"en": "The application service encountered an error. See details for more information."
|
|
111
120
|
}
|
|
112
121
|
}
|
|
113
122
|
}
|
package/bin/settings.json
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"messageQueuePrefix": "ti:messages:",
|
|
27
27
|
"messageStore": "ti:messages:store",
|
|
28
28
|
"securityHashEnabled": true,
|
|
29
|
-
"securityHashKey": "
|
|
29
|
+
"securityHashKey": "",
|
|
30
30
|
"traceExpirationTime": 3600,
|
|
31
31
|
"traceLogEnabled": false,
|
|
32
32
|
"traceRepository": "ti:messages:trace"
|
package/components/auditing.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -11,20 +11,8 @@ const _ = require( "lodash" );
|
|
|
11
11
|
const tools = require( "#tools" );
|
|
12
12
|
const logger = require( "#logger" );
|
|
13
13
|
const config = require( "#config" );
|
|
14
|
-
const gcloud = require( "#gcloud-integration" );
|
|
15
14
|
const ServiceInstance = require( "#service-instance" );
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
* @typedef {Object} TiLogEntry
|
|
19
|
-
* @property {string} _id Unique identifier that can be used to identify the document in a NoSQL database.
|
|
20
|
-
* @property {TiLogSeverity} severity The log severity level.
|
|
21
|
-
* @property {string} thread The categorization of the log message.
|
|
22
|
-
* @property {string} reporter
|
|
23
|
-
* @property {string} message The actual log message.
|
|
24
|
-
* @property {number} timestamp The timestamp of the log entry in UTC time.
|
|
25
|
-
* @property {Object} data Additional JSON data to go with the message.
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
16
|
/**
|
|
29
17
|
* Used to create and/or return an Auditing System singleton instance.
|
|
30
18
|
*
|
|
@@ -72,11 +60,6 @@ class Auditing {
|
|
|
72
60
|
if ( config.getSetting( config.setting.AUDITING_LOG_CONSOLE_ENABLED ) === true && console ) {
|
|
73
61
|
Auditing.#logToConsole( logEntry );
|
|
74
62
|
}
|
|
75
|
-
|
|
76
|
-
// If this is an actual error, then send it to GCloud error reporting system as well:
|
|
77
|
-
if ( logEntry.severity >= logger.logSeverity.WARNING && data instanceof Error && gcloud.isEnabled() ) {
|
|
78
|
-
gcloud.reportError( data );
|
|
79
|
-
}
|
|
80
63
|
}
|
|
81
64
|
} catch {
|
|
82
65
|
// do nothing here for now...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -19,7 +19,7 @@ class ConnectionObserver {
|
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* @constructor
|
|
22
|
-
* @throws {
|
|
22
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
23
23
|
*/
|
|
24
24
|
constructor() {
|
|
25
25
|
// make sure this abstract class cannot be instantiated:
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
|
+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
|
+
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Configuration Definitions:
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {string} EnvironmentVariable
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {NodeJS.Process} Environment
|
|
17
|
+
* @property {ProcessEnv} env
|
|
18
|
+
* @property {EnvironmentVariable} env.TI_GCLOUD_API_KEY
|
|
19
|
+
* @property {EnvironmentVariable} env.TI_GCLOUD_ENABLED
|
|
20
|
+
* @property {EnvironmentVariable} env.TI_GCLOUD_PROJECT_ID
|
|
21
|
+
* @property {EnvironmentVariable} env.TI_INSTANCE_CLASS
|
|
22
|
+
* @property {EnvironmentVariable} env.TI_INSTANCE_CONFIG
|
|
23
|
+
* @property {EnvironmentVariable} env.TI_INSTANCE_ID
|
|
24
|
+
* @property {EnvironmentVariable} env.TI_INSTANCE_NAME
|
|
25
|
+
* @property {EnvironmentVariable} env.TI_AUDITING_LOG_CONSOLE_ENABLED
|
|
26
|
+
* @property {EnvironmentVariable} env.TI_AUDITING_LOG_DETAILS
|
|
27
|
+
* @property {EnvironmentVariable} env.TI_AUDITING_LOG_MIN_LEVEL
|
|
28
|
+
* @property {EnvironmentVariable} env.TI_AUDITING_LOG_USES_JSON
|
|
29
|
+
* @property {EnvironmentVariable} env.TI_LOCALIZATION_LABELS_PATH
|
|
30
|
+
* @property {EnvironmentVariable} env.TI_LOCALIZATION_LANGUAGE
|
|
31
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_AUTH_KEY
|
|
32
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_DB
|
|
33
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_HOST
|
|
34
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_REDIS_PORT
|
|
35
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_RETRY_MAX_ATTEMPTS
|
|
36
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_RETRY_MAX_INTERVAL
|
|
37
|
+
* @property {EnvironmentVariable} env.TI_MEMORY_CACHE_USER
|
|
38
|
+
* @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_ENABLED
|
|
39
|
+
* @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY
|
|
40
|
+
* @property {EnvironmentVariable} env.TI_MESSAGE_EXCHANGE_TRACE_LOG_ENABLED
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @typedef {Object} SettingsMain
|
|
45
|
+
* @property {SettingsAuditing} auditing
|
|
46
|
+
* @property {SettingsGcloudIntegration} gcloudIntegration
|
|
47
|
+
* @property {SettingsLocalization} localization
|
|
48
|
+
* @property {SettingsMemoryCache} memoryCache
|
|
49
|
+
* @property {SettingsMessageExchange} messageExchange
|
|
50
|
+
* @property {SettingsServiceConfig} serviceConfig
|
|
51
|
+
* @property {string} operationMode
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {Object} SettingsAuditing
|
|
56
|
+
* @property {boolean} logConsoleEnabled
|
|
57
|
+
* @property {boolean} logDetails
|
|
58
|
+
* @property {TiLogSeverity} logMinLevel
|
|
59
|
+
* @property {boolean} logUsesJSON
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @typedef {Object} SettingsGcloudIntegration
|
|
64
|
+
* @property {string} apiKey
|
|
65
|
+
* @property {string} projectID
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @typedef {Object} SettingsLocalization
|
|
70
|
+
* @property {Array<string>} labelsPath
|
|
71
|
+
* @property {TiLocalizationLanguage} language
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* @typedef {Object} SettingsMemoryCache
|
|
76
|
+
* @property {string} authKey
|
|
77
|
+
* @property {number} redisDB
|
|
78
|
+
* @property {string} redisHost
|
|
79
|
+
* @property {number} redisPort
|
|
80
|
+
* @property {number} retryMaxAttempts
|
|
81
|
+
* @property {number} retryMaxInterval
|
|
82
|
+
* @property {string} user
|
|
83
|
+
*/
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* @typedef {Object} SettingsMessageExchange
|
|
87
|
+
* @property {string} messageQueuePrefix
|
|
88
|
+
* @property {string} messageStore
|
|
89
|
+
* @property {boolean} securityHashEnabled
|
|
90
|
+
* @property {string} securityHashKey
|
|
91
|
+
* @property {number} traceExpirationTime
|
|
92
|
+
* @property {boolean} traceLogEnabled
|
|
93
|
+
* @property {string} traceRepository
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* @typedef {Object} SettingsServiceConfig
|
|
98
|
+
* @property {number} executionTimeout
|
|
99
|
+
* @property {string} healthCheckAddress
|
|
100
|
+
* @property {CronString} healthCheckInterval
|
|
101
|
+
* @property {number} healthCheckTimeout
|
|
102
|
+
* @property {string} serviceRegistryAddress
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
// Utility Definitions:
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* @typedef {string} CronString
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @typedef {Object} TiEnumValue
|
|
113
|
+
* @property {number|string} value
|
|
114
|
+
* @property {string} name
|
|
115
|
+
* @property {string} [description]
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @typedef {Object} TiEnum
|
|
120
|
+
* @property {Object.<number|string,TiEnumValue>} properties
|
|
121
|
+
* @property {function( (number|string), [string] ): (string|undefined)} name
|
|
122
|
+
* @property {function( (number|string), [string] ): (string|undefined)} description
|
|
123
|
+
* @property {function( (number|string) ): boolean} contains
|
|
124
|
+
*/
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @typedef {Object} TiLogEntry
|
|
128
|
+
* @property {string} _id Unique identifier that can be used to identify the document in a NoSQL database.
|
|
129
|
+
* @property {TiLogSeverity} severity The log severity level.
|
|
130
|
+
* @property {string} thread The categorization of the log message.
|
|
131
|
+
* @property {string} reporter
|
|
132
|
+
* @property {string} message The actual log message.
|
|
133
|
+
* @property {number} timestamp The timestamp of the log entry in UTC time.
|
|
134
|
+
* @property {Object} data Additional JSON data to go with the message.
|
|
135
|
+
*/
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* @typedef {Object} TiTraceEntry
|
|
139
|
+
* @property {string} chainID
|
|
140
|
+
* @property {string} dispatchEvent
|
|
141
|
+
* @property {string} fromAddress
|
|
142
|
+
* @property {string} messageID
|
|
143
|
+
* @property {Object} messageSnapshot
|
|
144
|
+
* @property {string} messageState
|
|
145
|
+
* @property {string} messageType
|
|
146
|
+
* @property {string} toAddress
|
|
147
|
+
* @property {string} traceID
|
|
148
|
+
* @property {number} traceTimestamp
|
|
149
|
+
*/
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The key of this object is the language code, and the value is the textual representation of the label.
|
|
153
|
+
*
|
|
154
|
+
* @typedef {Object<TiLocalizationLanguage, string>} TiLocalizedLabel
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* A nested labels tree where intermediate nodes are objects and leaf nodes are language-to-text maps.
|
|
159
|
+
*
|
|
160
|
+
* @typedef {Object<string, TiLocalizedLabel | TiLabelsTree>} TiLabelsTree
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
// Service Bus Definitions:
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @typedef {Object} ServiceAddress
|
|
167
|
+
* @property {string} serviceAlias A valid service alias.
|
|
168
|
+
* @property {string} serviceDomainName A valid service domain name.
|
|
169
|
+
* @property {number|undefined} serviceVersion Optional service version. If not provided, the latest version will be assumed as a target.
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @typedef {Object} ServiceExecContext
|
|
174
|
+
* @property {string|undefined} authToken A valid authentication token that initialized the service call (if applicable).
|
|
175
|
+
* @property {ServiceCallPredecessor|undefined} previousServiceCall The previous service call in the execution chain (if such exists).
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* @typedef {Message} ServiceCallPredecessor
|
|
180
|
+
* @property {string} predecessor The {@link Message.messageID} of the predecessor in the service call tree.
|
|
181
|
+
* @property {ServiceAddress} serviceAddress The address of the service that has to process the service call.
|
|
182
|
+
* @property {Object|undefined} serviceParams The named params to be provided to the API service.
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @typedef {ServiceCallPredecessor} ServiceCall
|
|
187
|
+
* @property {string} authToken A valid authentication token that initialized the service call.
|
|
188
|
+
* @property {number} createdOn A unix timestamp taken at creation time of the service call.
|
|
189
|
+
* @property {number} executionTime The total execution time of this service call in milliseconds.
|
|
190
|
+
* @property {Object|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
|
|
191
|
+
* @property {number|undefined} finishedOn A unix timestamp taken at finish time of the service call.
|
|
192
|
+
* @property {boolean} isCompleted Flag to indicate if this service call has been completed.
|
|
193
|
+
* @property {boolean|undefined} isSuccessful A flag indicating if this service call can be considered successful or not. Will be 'undefined' until the service call is processed.
|
|
194
|
+
* @property {string[]} successors The service call IDs of the successors in the service call tree.
|
|
195
|
+
*/
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @typedef {Object} ServiceCallResult
|
|
199
|
+
* @property {TiException|undefined} exception If there was exception during the service call processing, it will be set here. Otherwise, it will be 'undefined'.
|
|
200
|
+
* @property {boolean} isSuccessful A flag indicating if this service call can be considered successful or not.
|
|
201
|
+
* @property {Object|string|undefined} payload The payload containing the results from the service call processing. If a string, it is ID of the payload in the memory cache instead.
|
|
202
|
+
*/
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @typedef {Object} ServiceDefinition
|
|
206
|
+
* @property {string} serviceAlias Service alias.
|
|
207
|
+
* @property {string} serviceFile The JS file containing the service itself. This has to be exposed via package.json import structure!
|
|
208
|
+
* @property {number} [serviceVersion] Service version.
|
|
209
|
+
*/
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @typedef {Object.<string, ServiceInterfaceVersion>} ServiceInterface
|
|
213
|
+
*/
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* @typedef {Object.<number, ServiceHandlerMethod>} ServiceInterfaceVersion
|
|
217
|
+
*/
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* @typedef {Object} ServiceConfiguration
|
|
221
|
+
* @property {ServiceDefinition[]} [services] A list of service definitions to be registered with the {@link ServiceProvider}.
|
|
222
|
+
*/
|
|
223
|
+
|
|
224
|
+
// Message Exchange Definitions:
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* @typedef {Object} MessageDestination
|
|
228
|
+
* @property {string|undefined} [instanceID] The instance ID of the message exchange by which the message was received (available after acceptance).
|
|
229
|
+
* @property {string} route The route to destination for the message. The exact structure will depend on the implementation of the message exchange.
|
|
230
|
+
*/
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* @typedef {Object} MessageSource
|
|
234
|
+
* @property {string} instanceID The instance ID of the message exchange from which the service call originated.
|
|
235
|
+
* @property {string} route The route from source of the message. The exact structure will depend on the implementation of the message exchange.
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @typedef {Object} Message
|
|
240
|
+
* @property {string} chainID Unique identifier of the message chain if the message is part of one.
|
|
241
|
+
* @property {number} chainLevel The node level of this message in the message chain tree.
|
|
242
|
+
* @property {MessageDestination} destination The destination of the message.
|
|
243
|
+
* @property {string} [hash] Security hash for the message if the mechanism is enabled.
|
|
244
|
+
* @property {string} messageID Unique message identifier.
|
|
245
|
+
* @property {Object|string|undefined} payload The message contents to be processed in destination. If a string, it is ID of the payload in the memory cache instead.
|
|
246
|
+
* Note that if this is not an Object or a string, there is no guarantee that it will be delivered in the same/proper format!
|
|
247
|
+
* @property {MessageSource} source The source of the message.
|
|
248
|
+
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -11,34 +11,10 @@ const _ = require( "lodash" );
|
|
|
11
11
|
const exceptions = require( "#exceptions" );
|
|
12
12
|
const messageTracer = require( "#message-tracer" );
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {Object} MessageDestination
|
|
16
|
-
* @property {string|undefined} [instanceID] The instance ID of the message exchange by which the message was received (available after acceptance).
|
|
17
|
-
* @property {string} route The route to destination for the message. Exact structure will depend on the implementation of the message exchange.
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* @typedef {Object} MessageSource
|
|
22
|
-
* @property {string} instanceID The instance ID of the message exchange from which the service call originated.
|
|
23
|
-
* @property {string} route The route from source of the message. Exact structure will depend on the implementation of the message exchange.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @typedef {Object} Message
|
|
28
|
-
* @property {string} chainID Unique identifier of the message chain if the message is part of one.
|
|
29
|
-
* @property {number} chainLevel The node level of this message in the message chain tree.
|
|
30
|
-
* @property {MessageDestination} destination The destination of the message.
|
|
31
|
-
* @property {string} [hash] Security hash for the message if the mechanism is enabled.
|
|
32
|
-
* @property {string} messageID Unique message identifier.
|
|
33
|
-
* @property {Object|string|undefined} payload The message contents to be processed in destination. If string it is ID of the payload in the memory cache instead.
|
|
34
|
-
* Note that if this is not an Object or a string, there is no guarantee that it will be delivered in the same/proper format!
|
|
35
|
-
* @property {MessageSource} source The source of the message.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
14
|
/**
|
|
39
15
|
* An abstract class that defines a message exchange behavior.
|
|
40
16
|
* <br/>
|
|
41
|
-
* NOTE: While this sets the basis frame for the message
|
|
17
|
+
* NOTE: While this sets the basis frame for the message-based communication between microservices, it has to be inherited and
|
|
42
18
|
* extended with additional logic that is NOT implemented here. For a working example please see {@link DefaultMessageExchange} class.
|
|
43
19
|
* <br/>
|
|
44
20
|
* NOTE: This class and its children are designed to be used internally by the {@link MessageDispatcher} and its related classes.
|
|
@@ -72,7 +48,7 @@ class MessageExchange extends MessageObserver {
|
|
|
72
48
|
* @constructor
|
|
73
49
|
* @param {string} instanceID The unique identifier of the microservice instance using the message exchange.
|
|
74
50
|
* @param {string} serviceDomainName The domain name of the microservice using the message exchange.
|
|
75
|
-
* @throws {
|
|
51
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
76
52
|
*/
|
|
77
53
|
constructor( instanceID, serviceDomainName ) {
|
|
78
54
|
super( 9 );
|
|
@@ -408,7 +384,7 @@ class MessageExchange extends MessageObserver {
|
|
|
408
384
|
}
|
|
409
385
|
|
|
410
386
|
/**
|
|
411
|
-
* Used only for the
|
|
387
|
+
* Used only for the message tracer.
|
|
412
388
|
*
|
|
413
389
|
* @method
|
|
414
390
|
* @param {string} identifier The identifier of the observed connection.
|
|
@@ -443,7 +419,7 @@ class MessageExchange extends MessageObserver {
|
|
|
443
419
|
|
|
444
420
|
/**
|
|
445
421
|
* Used to send a message request. Override of this method assumes that the message itself contains enough
|
|
446
|
-
* information to determine the
|
|
422
|
+
* information to determine the sending destination.
|
|
447
423
|
*
|
|
448
424
|
* @method
|
|
449
425
|
* @param {Message} message The message request to send.
|
|
@@ -457,7 +433,7 @@ class MessageExchange extends MessageObserver {
|
|
|
457
433
|
|
|
458
434
|
/**
|
|
459
435
|
* Used to send a message response. Override of this method assumes that the message itself contains enough
|
|
460
|
-
* information to determine the
|
|
436
|
+
* information to determine the sending destination.
|
|
461
437
|
*
|
|
462
438
|
* @method
|
|
463
439
|
* @param {Message} message The message response to send.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -8,12 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
const ConnectionObserver = require( "#connection-observer" );
|
|
10
10
|
const _ = require( "lodash" );
|
|
11
|
-
const
|
|
11
|
+
const crypto = require( "node:crypto" );
|
|
12
12
|
const exceptions = require( "#exceptions" );
|
|
13
13
|
const logger = require( "#logger" );
|
|
14
14
|
const tools = require( "#tools" );
|
|
15
15
|
const config = require( "#config" );
|
|
16
16
|
|
|
17
|
+
const OLD_DEFAULT_HASH_KEY = "23e7bdc7-a793-41f9-856e-6760332f0c73";
|
|
18
|
+
let keyWarningEmitted = false;
|
|
19
|
+
|
|
17
20
|
/**
|
|
18
21
|
* An abstract class that defines a basic message handler behavior.
|
|
19
22
|
* <br/>
|
|
@@ -33,7 +36,7 @@ class MessageHandler extends ConnectionObserver {
|
|
|
33
36
|
/**
|
|
34
37
|
* @constructor
|
|
35
38
|
* @param {string} identifier An identifier for this message handler. Should be unique in the context of the message exchange.
|
|
36
|
-
* @throws {
|
|
39
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
37
40
|
*/
|
|
38
41
|
constructor( identifier ) {
|
|
39
42
|
super();
|
|
@@ -120,10 +123,17 @@ class MessageHandler extends ConnectionObserver {
|
|
|
120
123
|
* @public
|
|
121
124
|
*/
|
|
122
125
|
createMessageHash( message ) {
|
|
126
|
+
let key = config.getSetting( config.setting.MESSAGE_EXCHANGE_SECURITY_HASH_KEY );
|
|
127
|
+
if ( keyWarningEmitted === false ) {
|
|
128
|
+
keyWarningEmitted = true;
|
|
129
|
+
if ( !key || key === OLD_DEFAULT_HASH_KEY ) {
|
|
130
|
+
logger.log( "Message-exchange security hash is enabled but no private key is set ('securityHashKey' is missing or the published default). Set TI_MESSAGE_EXCHANGE_SECURITY_HASH_KEY to a private value, otherwise tamper protection is ineffective.", logger.logSeverity.WARNING );
|
|
131
|
+
}
|
|
132
|
+
}
|
|
123
133
|
let transformed = tools.decomposeJSON( tools.decycle( message ) );
|
|
124
|
-
let
|
|
125
|
-
|
|
126
|
-
return
|
|
134
|
+
let hmac = crypto.createHmac( "sha256", Buffer.from( key ) );
|
|
135
|
+
hmac.update( Buffer.from( transformed ) );
|
|
136
|
+
return hmac.digest( "hex" );
|
|
127
137
|
}
|
|
128
138
|
|
|
129
139
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -27,7 +27,7 @@ class MessageObserver extends ConnectionObserver {
|
|
|
27
27
|
/**
|
|
28
28
|
* @constructor
|
|
29
29
|
* @param {number} [priority=0] The priority of this observer. Higher values indicate higher priority.
|
|
30
|
-
* @throws {
|
|
30
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
31
31
|
*/
|
|
32
32
|
constructor( priority = 0 ) {
|
|
33
33
|
super();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* The ti-engine is an open source, free to use—both for personal and commercial projects—framework for the creation of microservice-based solutions using node.js.
|
|
3
|
-
* Copyright © 2021-
|
|
3
|
+
* Copyright © 2021-2026 Boris Kostadinov <kostadinov.boris@gmail.com>
|
|
4
4
|
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
|
5
5
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
6
6
|
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
@@ -10,6 +10,7 @@ const MessageHandler = require( "#message-handler" );
|
|
|
10
10
|
const logger = require( "#logger" );
|
|
11
11
|
const exceptions = require( "#exceptions" );
|
|
12
12
|
const config = require( "#config" );
|
|
13
|
+
const tools = require( "#tools" );
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* An abstract class that defines a basic message receiver behavior.
|
|
@@ -28,7 +29,7 @@ class MessageReceiver extends MessageHandler {
|
|
|
28
29
|
* @constructor
|
|
29
30
|
* @param {string} identifier An identifier for this message handler. Should be unique in the context of the message exchange.
|
|
30
31
|
* @param {string} receiveQueue The queue from which the messages will be received.
|
|
31
|
-
* @throws {
|
|
32
|
+
* @throws {TiException.E_GEN_ABSTRACT_CLASS_INIT} If this class is instantiated directly.
|
|
32
33
|
*/
|
|
33
34
|
constructor( identifier, receiveQueue ) {
|
|
34
35
|
super( identifier );
|
|
@@ -161,7 +162,7 @@ class MessageReceiver extends MessageHandler {
|
|
|
161
162
|
let receivedHash = message.hash;
|
|
162
163
|
delete message.hash;
|
|
163
164
|
let currentHash = this.createMessageHash( message );
|
|
164
|
-
if (
|
|
165
|
+
if ( tools.constantTimeEquals( receivedHash, currentHash ) ) {
|
|
165
166
|
resolve( message );
|
|
166
167
|
} else {
|
|
167
168
|
reject( exceptions.raise( exceptions.exceptionCode.E_SEC_MESSAGE_TAMPERING_DETECTED, {
|