@naylence/runtime 0.4.5 → 0.4.7
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/dist/browser/index.cjs +179 -127
- package/dist/browser/index.mjs +177 -129
- package/dist/cjs/naylence/fame/delivery/delivery-profile-factory.js +5 -9
- package/dist/cjs/naylence/fame/index.js +1 -0
- package/dist/cjs/naylence/fame/node/admission/admission-profile-factory.js +15 -19
- package/dist/cjs/naylence/fame/node/node-identity-policy-profile-factory.js +6 -10
- package/dist/cjs/naylence/fame/profile/index.js +8 -0
- package/dist/cjs/naylence/fame/profile/profile-registry.js +57 -0
- package/dist/cjs/naylence/fame/security/auth/authorization-profile-factory.js +64 -30
- package/dist/cjs/naylence/fame/security/default-security-manager-factory.js +4 -3
- package/dist/cjs/naylence/fame/security/node-security-profile-factory.js +9 -13
- package/dist/cjs/naylence/fame/sentinel/load-balancing/load-balancing-profile-factory.js +10 -13
- package/dist/cjs/naylence/fame/sentinel/routing-profile-factory.js +7 -8
- package/dist/cjs/naylence/fame/storage/storage-profile-factory.js +8 -12
- package/dist/cjs/naylence/fame/telemetry/trace-emitter-profile-factory.js +5 -9
- package/dist/cjs/runtime-isomorphic.js +1 -0
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/delivery/delivery-profile-factory.js +5 -9
- package/dist/esm/naylence/fame/index.js +1 -0
- package/dist/esm/naylence/fame/node/admission/admission-profile-factory.js +15 -19
- package/dist/esm/naylence/fame/node/node-identity-policy-profile-factory.js +6 -10
- package/dist/esm/naylence/fame/profile/index.js +1 -0
- package/dist/esm/naylence/fame/profile/profile-registry.js +51 -0
- package/dist/esm/naylence/fame/security/auth/authorization-profile-factory.js +65 -31
- package/dist/esm/naylence/fame/security/default-security-manager-factory.js +4 -3
- package/dist/esm/naylence/fame/security/node-security-profile-factory.js +9 -13
- package/dist/esm/naylence/fame/sentinel/load-balancing/load-balancing-profile-factory.js +10 -13
- package/dist/esm/naylence/fame/sentinel/routing-profile-factory.js +7 -8
- package/dist/esm/naylence/fame/storage/storage-profile-factory.js +8 -12
- package/dist/esm/naylence/fame/telemetry/trace-emitter-profile-factory.js +5 -9
- package/dist/esm/runtime-isomorphic.js +1 -0
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +179 -127
- package/dist/node/index.mjs +177 -129
- package/dist/node/node.cjs +182 -128
- package/dist/node/node.mjs +180 -130
- package/dist/types/naylence/fame/index.d.ts +1 -0
- package/dist/types/naylence/fame/profile/index.d.ts +2 -0
- package/dist/types/naylence/fame/profile/profile-registry.d.ts +9 -0
- package/dist/types/runtime-isomorphic.d.ts +1 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Expressions } from '@naylence/factory';
|
|
2
2
|
import { GRANT_PURPOSE_NODE_ATTACH } from '../../grants/grant.js';
|
|
3
3
|
import { getLogger } from '../../util/logging.js';
|
|
4
|
+
import { getProfile, registerProfile, } from '../../profile/profile-registry.js';
|
|
4
5
|
import { ADMISSION_CLIENT_FACTORY_BASE_TYPE, AdmissionClientFactory, } from './admission-client-factory.js';
|
|
5
6
|
const logger = getLogger('naylence.fame.node.admission.admission_profile_factory');
|
|
6
7
|
const ENV_VAR_IS_ROOT = 'FAME_ROOT';
|
|
@@ -211,20 +212,18 @@ const NOOP_PROFILE = {
|
|
|
211
212
|
auto_accept_logicals: true,
|
|
212
213
|
autoAcceptLogicals: true,
|
|
213
214
|
};
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
[PROFILE_NAME_NONE]: NOOP_PROFILE,
|
|
227
|
-
};
|
|
215
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_WELCOME, WELCOME_SERVICE_PROFILE, { source: 'admission-profile-factory' });
|
|
216
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_WELCOME_PKCE, WELCOME_SERVICE_PKCE_PROFILE, { source: 'admission-profile-factory' });
|
|
217
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_WELCOME_PKCE_ALIAS, WELCOME_SERVICE_PKCE_PROFILE, { source: 'admission-profile-factory' });
|
|
218
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT, DIRECT_PROFILE, { source: 'admission-profile-factory' });
|
|
219
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT_PKCE, DIRECT_PKCE_PROFILE, { source: 'admission-profile-factory' });
|
|
220
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT_PKCE_ALIAS, DIRECT_PKCE_PROFILE, { source: 'admission-profile-factory' });
|
|
221
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT_HTTP, DIRECT_HTTP_PROFILE, { source: 'admission-profile-factory' });
|
|
222
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT_INPAGE, DIRECT_INPAGE_PROFILE, { source: 'admission-profile-factory' });
|
|
223
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_DIRECT_INPAGE_ALIAS, DIRECT_INPAGE_PROFILE, { source: 'admission-profile-factory' });
|
|
224
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_OPEN, OPEN_PROFILE, { source: 'admission-profile-factory' });
|
|
225
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_NOOP, NOOP_PROFILE, { source: 'admission-profile-factory' });
|
|
226
|
+
registerProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, PROFILE_NAME_NONE, NOOP_PROFILE, { source: 'admission-profile-factory' });
|
|
228
227
|
export const FACTORY_META = {
|
|
229
228
|
base: ADMISSION_CLIENT_FACTORY_BASE_TYPE,
|
|
230
229
|
key: 'AdmissionProfile',
|
|
@@ -261,13 +260,10 @@ function normalizeConfig(config) {
|
|
|
261
260
|
return { profile: normalizedProfile };
|
|
262
261
|
}
|
|
263
262
|
function resolveProfileConfig(profileName) {
|
|
264
|
-
const profile =
|
|
263
|
+
const profile = getProfile(ADMISSION_CLIENT_FACTORY_BASE_TYPE, profileName);
|
|
265
264
|
if (!profile) {
|
|
266
265
|
throw new Error(`Unknown admission profile: ${profileName}`);
|
|
267
266
|
}
|
|
268
|
-
return
|
|
269
|
-
}
|
|
270
|
-
function deepClone(value) {
|
|
271
|
-
return JSON.parse(JSON.stringify(value));
|
|
267
|
+
return profile;
|
|
272
268
|
}
|
|
273
269
|
export default AdmissionProfileFactory;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE, NodeIdentityPolicyFactory, } from './node-identity-policy-factory.js';
|
|
2
2
|
import { getLogger } from '../util/logging.js';
|
|
3
|
+
import { getProfile, registerProfile, } from '../profile/profile-registry.js';
|
|
3
4
|
const logger = getLogger('naylence.fame.node.node_identity_policy_profile_factory');
|
|
4
5
|
const PROFILE_NAME_DEFAULT = 'default';
|
|
5
6
|
const PROFILE_NAME_TOKEN_SUBJECT = 'token-subject';
|
|
@@ -10,11 +11,9 @@ const DEFAULT_PROFILE = {
|
|
|
10
11
|
const TOKEN_SUBJECT_PROFILE = {
|
|
11
12
|
type: 'TokenSubjectNodeIdentityPolicy',
|
|
12
13
|
};
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
[PROFILE_NAME_TOKEN_SUBJECT_ALIAS]: TOKEN_SUBJECT_PROFILE,
|
|
17
|
-
};
|
|
14
|
+
registerProfile(NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE, PROFILE_NAME_DEFAULT, DEFAULT_PROFILE, { source: 'node-identity-policy-profile-factory' });
|
|
15
|
+
registerProfile(NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE, PROFILE_NAME_TOKEN_SUBJECT, TOKEN_SUBJECT_PROFILE, { source: 'node-identity-policy-profile-factory' });
|
|
16
|
+
registerProfile(NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE, PROFILE_NAME_TOKEN_SUBJECT_ALIAS, TOKEN_SUBJECT_PROFILE, { source: 'node-identity-policy-profile-factory' });
|
|
18
17
|
export const FACTORY_META = {
|
|
19
18
|
base: NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE,
|
|
20
19
|
key: 'NodeIdentityPolicyProfile',
|
|
@@ -51,13 +50,10 @@ function normalizeConfig(config) {
|
|
|
51
50
|
return { profile: normalizedProfile };
|
|
52
51
|
}
|
|
53
52
|
function resolveProfileConfig(profileName) {
|
|
54
|
-
const profile =
|
|
53
|
+
const profile = getProfile(NODE_IDENTITY_POLICY_FACTORY_BASE_TYPE, profileName);
|
|
55
54
|
if (!profile) {
|
|
56
55
|
throw new Error(`Unknown node identity policy profile: ${profileName}`);
|
|
57
56
|
}
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
function deepClone(value) {
|
|
61
|
-
return JSON.parse(JSON.stringify(value));
|
|
57
|
+
return profile;
|
|
62
58
|
}
|
|
63
59
|
export default NodeIdentityPolicyProfileFactory;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { registerProfile, getProfile, listProfiles, clearProfiles, } from './profile-registry.js';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const registry = new Map();
|
|
2
|
+
function normalizeKey(value, label) {
|
|
3
|
+
if (typeof value !== 'string') {
|
|
4
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
5
|
+
}
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
if (!trimmed) {
|
|
8
|
+
throw new Error(`${label} must be a non-empty string`);
|
|
9
|
+
}
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
function cloneConfig(value) {
|
|
13
|
+
return JSON.parse(JSON.stringify(value));
|
|
14
|
+
}
|
|
15
|
+
export function registerProfile(baseType, name, config, options) {
|
|
16
|
+
const normalizedBase = normalizeKey(baseType, 'baseType');
|
|
17
|
+
const normalizedName = normalizeKey(name, 'profile name');
|
|
18
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
19
|
+
throw new Error(`Profile '${normalizedName}' config must be an object`);
|
|
20
|
+
}
|
|
21
|
+
const profiles = registry.get(normalizedBase) ?? new Map();
|
|
22
|
+
if (profiles.has(normalizedName) && options?.allowOverride !== true) {
|
|
23
|
+
const sourceLabel = options?.source ? ` (${options.source})` : '';
|
|
24
|
+
throw new Error(`Profile '${normalizedName}' already registered for ${normalizedBase}${sourceLabel}`);
|
|
25
|
+
}
|
|
26
|
+
profiles.set(normalizedName, config);
|
|
27
|
+
registry.set(normalizedBase, profiles);
|
|
28
|
+
}
|
|
29
|
+
export function getProfile(baseType, name) {
|
|
30
|
+
const normalizedBase = normalizeKey(baseType, 'baseType');
|
|
31
|
+
const normalizedName = normalizeKey(name, 'profile name');
|
|
32
|
+
const profiles = registry.get(normalizedBase);
|
|
33
|
+
if (!profiles) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const profile = profiles.get(normalizedName);
|
|
37
|
+
return profile ? cloneConfig(profile) : null;
|
|
38
|
+
}
|
|
39
|
+
export function listProfiles(baseType) {
|
|
40
|
+
const normalizedBase = normalizeKey(baseType, 'baseType');
|
|
41
|
+
const profiles = registry.get(normalizedBase);
|
|
42
|
+
return profiles ? Array.from(profiles.keys()) : [];
|
|
43
|
+
}
|
|
44
|
+
export function clearProfiles(baseType) {
|
|
45
|
+
if (!baseType) {
|
|
46
|
+
registry.clear();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const normalizedBase = normalizeKey(baseType, 'baseType');
|
|
50
|
+
registry.delete(normalizedBase);
|
|
51
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Expressions,
|
|
1
|
+
import { Expressions, configValidator } from '@naylence/factory';
|
|
2
2
|
import { getLogger } from '../../util/logging.js';
|
|
3
3
|
import { AUTHORIZER_FACTORY_BASE_TYPE, AuthorizerFactory, } from './authorizer-factory.js';
|
|
4
|
+
import { getProfile, registerProfile, } from '../../profile/profile-registry.js';
|
|
4
5
|
const logger = getLogger('naylence.fame.security.auth.authorization_profile_factory');
|
|
5
6
|
export const PROFILE_NAME_DEFAULT = 'jwt';
|
|
6
7
|
export const PROFILE_NAME_OAUTH2 = 'oauth2';
|
|
@@ -21,14 +22,13 @@ export const ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE = 'FAME_JWT_REVERSE_AUTH_AUDIENCE
|
|
|
21
22
|
export const ENV_VAR_HMAC_SECRET = 'FAME_HMAC_SECRET';
|
|
22
23
|
const DEFAULT_REVERSE_AUTH_ISSUER = 'reverse-auth.naylence.ai';
|
|
23
24
|
const DEFAULT_REVERSE_AUTH_AUDIENCE = 'dev.naylence.ai';
|
|
24
|
-
const DEFAULT_VERIFIER_CONFIG = {
|
|
25
|
-
type: 'JWKSJWTTokenVerifier',
|
|
26
|
-
jwks_url: Expressions.env(ENV_VAR_JWKS_URL),
|
|
27
|
-
issuer: Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER),
|
|
28
|
-
};
|
|
29
25
|
const DEFAULT_PROFILE = {
|
|
30
26
|
type: 'DefaultAuthorizer',
|
|
31
|
-
verifier:
|
|
27
|
+
verifier: {
|
|
28
|
+
type: 'JWKSJWTTokenVerifier',
|
|
29
|
+
jwks_url: Expressions.env(ENV_VAR_JWKS_URL),
|
|
30
|
+
issuer: Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER),
|
|
31
|
+
},
|
|
32
32
|
};
|
|
33
33
|
const OAUTH2_PROFILE = {
|
|
34
34
|
type: 'OAuth2Authorizer',
|
|
@@ -73,6 +73,11 @@ const OAUTH2_CALLBACK_PROFILE = {
|
|
|
73
73
|
const NOOP_PROFILE = {
|
|
74
74
|
type: 'NoopAuthorizer',
|
|
75
75
|
};
|
|
76
|
+
const DEFAULT_VERIFIER_CONFIG = {
|
|
77
|
+
type: 'JWKSJWTTokenVerifier',
|
|
78
|
+
jwks_url: Expressions.env(ENV_VAR_JWKS_URL),
|
|
79
|
+
issuer: Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER),
|
|
80
|
+
};
|
|
76
81
|
const DEFAULT_POLICY_SOURCE = {
|
|
77
82
|
type: 'LocalFileAuthorizationPolicySource',
|
|
78
83
|
path: Expressions.env(ENV_VAR_AUTH_POLICY_PATH, './auth-policy.yaml'),
|
|
@@ -83,14 +88,12 @@ const POLICY_LOCALFILE_PROFILE = {
|
|
|
83
88
|
verifier: DEFAULT_VERIFIER_CONFIG,
|
|
84
89
|
policySource: DEFAULT_POLICY_SOURCE,
|
|
85
90
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
[PROFILE_NAME_NOOP]: NOOP_PROFILE,
|
|
93
|
-
};
|
|
91
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_DEFAULT, DEFAULT_PROFILE, { source: 'authorization-profile-factory' });
|
|
92
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_OAUTH2, OAUTH2_PROFILE, { source: 'authorization-profile-factory' });
|
|
93
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_OAUTH2_GATED, OAUTH2_GATED_PROFILE, { source: 'authorization-profile-factory' });
|
|
94
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_OAUTH2_CALLBACK, OAUTH2_CALLBACK_PROFILE, { source: 'authorization-profile-factory' });
|
|
95
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_POLICY_LOCALFILE, POLICY_LOCALFILE_PROFILE, { source: 'authorization-profile-factory' });
|
|
96
|
+
registerProfile(AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_NOOP, NOOP_PROFILE, { source: 'authorization-profile-factory' });
|
|
94
97
|
const PROFILE_ALIASES = {
|
|
95
98
|
jwt: PROFILE_NAME_DEFAULT,
|
|
96
99
|
jwks: PROFILE_NAME_DEFAULT,
|
|
@@ -124,13 +127,55 @@ export class AuthorizationProfileFactory extends AuthorizerFactory {
|
|
|
124
127
|
logger.debug('enabling_authorization_profile', {
|
|
125
128
|
profile: normalized.profile,
|
|
126
129
|
});
|
|
127
|
-
|
|
130
|
+
// Extract CreateResourceOptions from factoryArgs - it's typically the last object with env/config/variables
|
|
131
|
+
const createOptions = extractCreateResourceOptions(factoryArgs);
|
|
132
|
+
// Only evaluate expressions if we have env/config/variables available
|
|
133
|
+
let evaluatedConfig = profileConfig;
|
|
134
|
+
const hasContext = createOptions.env || createOptions.config || createOptions.variables;
|
|
135
|
+
if (hasContext) {
|
|
136
|
+
// Build validation context from createOptions to evaluate expressions
|
|
137
|
+
const validationContext = {
|
|
138
|
+
env: createOptions.env,
|
|
139
|
+
config: createOptions.config,
|
|
140
|
+
variables: createOptions.variables,
|
|
141
|
+
allowUnknownProperties: true,
|
|
142
|
+
};
|
|
143
|
+
// Evaluate expressions in the profile config
|
|
144
|
+
const validationResult = configValidator.validate(profileConfig, validationContext);
|
|
145
|
+
if (!validationResult.valid) {
|
|
146
|
+
const errorMessages = validationResult.errors
|
|
147
|
+
.map((error) => `${error.path || 'root'}: ${error.message}`)
|
|
148
|
+
.join('; ');
|
|
149
|
+
throw new Error(`Failed to evaluate authorization profile configuration: ${errorMessages}`);
|
|
150
|
+
}
|
|
151
|
+
evaluatedConfig = validationResult.config ?? profileConfig;
|
|
152
|
+
}
|
|
153
|
+
const authorizer = await AuthorizerFactory.createAuthorizer(evaluatedConfig, hasContext ? { validate: false } : { factoryArgs } // Pass factoryArgs if no validation was done
|
|
154
|
+
);
|
|
128
155
|
if (!authorizer) {
|
|
129
156
|
throw new Error(`Failed to create authorizer for profile: ${normalized.profile}`);
|
|
130
157
|
}
|
|
131
158
|
return authorizer;
|
|
132
159
|
}
|
|
133
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Extracts CreateResourceOptions from factoryArgs.
|
|
163
|
+
* The factory system passes CreateResourceOptions as an object in factoryArgs.
|
|
164
|
+
*/
|
|
165
|
+
function extractCreateResourceOptions(factoryArgs) {
|
|
166
|
+
// Find the last object argument that looks like CreateResourceOptions
|
|
167
|
+
for (let i = factoryArgs.length - 1; i >= 0; i--) {
|
|
168
|
+
const arg = factoryArgs[i];
|
|
169
|
+
if (arg && typeof arg === 'object' && !Array.isArray(arg)) {
|
|
170
|
+
const candidate = arg;
|
|
171
|
+
// Check if it has typical CreateResourceOptions properties
|
|
172
|
+
if ('env' in candidate || 'config' in candidate || 'variables' in candidate || 'factoryArgs' in candidate) {
|
|
173
|
+
return candidate;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
134
179
|
function normalizeConfig(config) {
|
|
135
180
|
if (!config) {
|
|
136
181
|
return { profile: PROFILE_NAME_OAUTH2 };
|
|
@@ -142,21 +187,13 @@ function normalizeConfig(config) {
|
|
|
142
187
|
return { profile: canonicalProfile };
|
|
143
188
|
}
|
|
144
189
|
function resolveProfileName(candidate) {
|
|
145
|
-
|
|
146
|
-
if (direct && ExpressionEvaluator.isExpression(direct)) {
|
|
147
|
-
const evaluated = ExpressionEvaluator.evaluate(direct);
|
|
148
|
-
direct = coerceProfileString(evaluated);
|
|
149
|
-
}
|
|
190
|
+
const direct = coerceProfileString(candidate.profile);
|
|
150
191
|
if (direct) {
|
|
151
192
|
return direct;
|
|
152
193
|
}
|
|
153
194
|
const legacyKeys = ['profile_name', 'profileName'];
|
|
154
195
|
for (const legacyKey of legacyKeys) {
|
|
155
|
-
|
|
156
|
-
if (legacyValue && ExpressionEvaluator.isExpression(legacyValue)) {
|
|
157
|
-
const evaluated = ExpressionEvaluator.evaluate(legacyValue);
|
|
158
|
-
legacyValue = coerceProfileString(evaluated);
|
|
159
|
-
}
|
|
196
|
+
const legacyValue = coerceProfileString(candidate[legacyKey]);
|
|
160
197
|
if (legacyValue) {
|
|
161
198
|
return legacyValue;
|
|
162
199
|
}
|
|
@@ -175,13 +212,10 @@ function canonicalizeProfileName(value) {
|
|
|
175
212
|
return PROFILE_ALIASES[normalized] ?? normalized;
|
|
176
213
|
}
|
|
177
214
|
function resolveProfileConfig(profileName) {
|
|
178
|
-
const profile =
|
|
215
|
+
const profile = getProfile(AUTHORIZER_FACTORY_BASE_TYPE, profileName);
|
|
179
216
|
if (!profile) {
|
|
180
217
|
throw new Error(`Unknown authorization profile: ${profileName}`);
|
|
181
218
|
}
|
|
182
|
-
return
|
|
183
|
-
}
|
|
184
|
-
function deepClone(value) {
|
|
185
|
-
return JSON.parse(JSON.stringify(value));
|
|
219
|
+
return profile;
|
|
186
220
|
}
|
|
187
221
|
export default AuthorizationProfileFactory;
|
|
@@ -156,7 +156,7 @@ export class DefaultSecurityManagerFactory extends SecurityManagerFactory {
|
|
|
156
156
|
}
|
|
157
157
|
if (!authorizer) {
|
|
158
158
|
authorizer =
|
|
159
|
-
await DefaultSecurityManagerFactory.createAuthorizerFromConfig(config, policy);
|
|
159
|
+
await DefaultSecurityManagerFactory.createAuthorizerFromConfig(config, policy, createOptions);
|
|
160
160
|
}
|
|
161
161
|
if (authorizer &&
|
|
162
162
|
eventListeners &&
|
|
@@ -387,14 +387,14 @@ export class DefaultSecurityManagerFactory extends SecurityManagerFactory {
|
|
|
387
387
|
}
|
|
388
388
|
return null;
|
|
389
389
|
}
|
|
390
|
-
static async createAuthorizerFromConfig(config, policy) {
|
|
390
|
+
static async createAuthorizerFromConfig(config, policy, createOptions) {
|
|
391
391
|
let authorizerConfig = config.authorizer ?? null;
|
|
392
392
|
if (!authorizerConfig) {
|
|
393
393
|
authorizerConfig = config.authorizer_config ?? null;
|
|
394
394
|
}
|
|
395
395
|
if (authorizerConfig &&
|
|
396
396
|
DefaultSecurityManagerFactory.isConfigLike(authorizerConfig)) {
|
|
397
|
-
return ((await AuthorizerFactory.createAuthorizer(authorizerConfig)) ?? null);
|
|
397
|
+
return ((await AuthorizerFactory.createAuthorizer(authorizerConfig, createOptions ?? undefined)) ?? null);
|
|
398
398
|
}
|
|
399
399
|
try {
|
|
400
400
|
const requirements = policy.requirements?.();
|
|
@@ -410,6 +410,7 @@ export class DefaultSecurityManagerFactory extends SecurityManagerFactory {
|
|
|
410
410
|
}
|
|
411
411
|
const tokenVerifier = new NoopTokenVerifier();
|
|
412
412
|
return ((await AuthorizerFactory.createAuthorizer(null, {
|
|
413
|
+
...createOptions,
|
|
413
414
|
factoryArgs: [tokenVerifier],
|
|
414
415
|
})) ?? null);
|
|
415
416
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Expressions, configValidator, createResource, } from '@naylence/factory';
|
|
2
2
|
import { SECURITY_MANAGER_FACTORY_BASE_TYPE, SecurityManagerFactory, } from './security-manager-factory.js';
|
|
3
3
|
import { getLogger } from '../util/logging.js';
|
|
4
|
+
import { getProfile, registerProfile, } from '../profile/profile-registry.js';
|
|
4
5
|
const logger = getLogger('naylence.fame.security.node_security_profile_factory');
|
|
5
6
|
export const ENV_VAR_JWT_TRUSTED_ISSUER = 'FAME_JWT_TRUSTED_ISSUER';
|
|
6
7
|
export const ENV_VAR_JWT_ALGORITHM = 'FAME_JWT_ALGORITHM';
|
|
@@ -268,14 +269,12 @@ const OPEN_PROFILE = {
|
|
|
268
269
|
profile: Expressions.env(ENV_VAR_AUTHORIZATION_PROFILE, 'noop'),
|
|
269
270
|
},
|
|
270
271
|
};
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
[PROFILE_NAME_OPEN]: OPEN_PROFILE,
|
|
278
|
-
};
|
|
272
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_OVERLAY, OVERLAY_PROFILE, { source: 'node-security-profile-factory' });
|
|
273
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_OVERLAY_CALLBACK, OVERLAY_CALLBACK_PROFILE, { source: 'node-security-profile-factory' });
|
|
274
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_STRICT_OVERLAY, STRICT_OVERLAY_PROFILE, { source: 'node-security-profile-factory' });
|
|
275
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_GATED, GATED_PROFILE, { source: 'node-security-profile-factory' });
|
|
276
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_GATED_CALLBACK, GATED_CALLBACK_PROFILE, { source: 'node-security-profile-factory' });
|
|
277
|
+
registerProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, PROFILE_NAME_OPEN, OPEN_PROFILE, { source: 'node-security-profile-factory' });
|
|
279
278
|
export const FACTORY_META = {
|
|
280
279
|
base: SECURITY_MANAGER_FACTORY_BASE_TYPE,
|
|
281
280
|
key: 'SecurityProfile',
|
|
@@ -382,13 +381,10 @@ function normalizeProfile(config) {
|
|
|
382
381
|
return value.toLowerCase();
|
|
383
382
|
}
|
|
384
383
|
function resolveProfileConfig(profileName) {
|
|
385
|
-
const template =
|
|
384
|
+
const template = getProfile(SECURITY_MANAGER_FACTORY_BASE_TYPE, profileName);
|
|
386
385
|
if (!template) {
|
|
387
386
|
throw new Error(`Unknown security profile: ${profileName}`);
|
|
388
387
|
}
|
|
389
|
-
return
|
|
390
|
-
}
|
|
391
|
-
function deepClone(value) {
|
|
392
|
-
return JSON.parse(JSON.stringify(value));
|
|
388
|
+
return template;
|
|
393
389
|
}
|
|
394
390
|
export default NodeSecurityProfileFactory;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createResource } from '@naylence/factory';
|
|
2
2
|
import { getLogger } from '../../util/logging.js';
|
|
3
|
+
import { getProfile, registerProfile, } from '../../profile/profile-registry.js';
|
|
3
4
|
import { LOAD_BALANCING_STRATEGY_FACTORY_BASE, LoadBalancingStrategyFactory, } from './load-balancing-strategy-factory.js';
|
|
4
5
|
const logger = getLogger('naylence.fame.sentinel.load_balancing.load_balancing_profile_factory');
|
|
5
6
|
export const PROFILE_NAME_RANDOM = 'random';
|
|
@@ -23,6 +24,11 @@ const STICKY_HRW_PROFILE = {
|
|
|
23
24
|
const DEVELOPMENT_PROFILE = {
|
|
24
25
|
type: 'RoundRobinLoadBalancingStrategy',
|
|
25
26
|
};
|
|
27
|
+
registerProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, PROFILE_NAME_RANDOM, RANDOM_PROFILE, { source: 'load-balancing-profile-factory' });
|
|
28
|
+
registerProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, PROFILE_NAME_ROUND_ROBIN, ROUND_ROBIN_PROFILE, { source: 'load-balancing-profile-factory' });
|
|
29
|
+
registerProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, PROFILE_NAME_HRW, HRW_PROFILE, { source: 'load-balancing-profile-factory' });
|
|
30
|
+
registerProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, PROFILE_NAME_STICKY_HRW, STICKY_HRW_PROFILE, { source: 'load-balancing-profile-factory' });
|
|
31
|
+
registerProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, PROFILE_NAME_DEVELOPMENT, DEVELOPMENT_PROFILE, { source: 'load-balancing-profile-factory' });
|
|
26
32
|
export const FACTORY_META = {
|
|
27
33
|
base: LOAD_BALANCING_STRATEGY_FACTORY_BASE,
|
|
28
34
|
key: 'LoadBalancingProfile',
|
|
@@ -77,20 +83,11 @@ export class LoadBalancingProfileFactory extends LoadBalancingStrategyFactory {
|
|
|
77
83
|
return undefined;
|
|
78
84
|
}
|
|
79
85
|
resolveProfile(profile) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
case PROFILE_NAME_ROUND_ROBIN:
|
|
84
|
-
return ROUND_ROBIN_PROFILE;
|
|
85
|
-
case PROFILE_NAME_HRW:
|
|
86
|
-
return HRW_PROFILE;
|
|
87
|
-
case PROFILE_NAME_STICKY_HRW:
|
|
88
|
-
return STICKY_HRW_PROFILE;
|
|
89
|
-
case PROFILE_NAME_DEVELOPMENT:
|
|
90
|
-
return DEVELOPMENT_PROFILE;
|
|
91
|
-
default:
|
|
92
|
-
throw new Error(`Unknown load balancing profile: ${profile}`);
|
|
86
|
+
const strategyConfig = getProfile(LOAD_BALANCING_STRATEGY_FACTORY_BASE, profile);
|
|
87
|
+
if (!strategyConfig) {
|
|
88
|
+
throw new Error(`Unknown load balancing profile: ${profile}`);
|
|
93
89
|
}
|
|
90
|
+
return strategyConfig;
|
|
94
91
|
}
|
|
95
92
|
}
|
|
96
93
|
export default LoadBalancingProfileFactory;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createResource } from '@naylence/factory';
|
|
2
2
|
import { getLogger } from '../util/logging.js';
|
|
3
|
+
import { getProfile, registerProfile, } from '../profile/profile-registry.js';
|
|
3
4
|
import { ROUTING_POLICY_FACTORY_BASE, RoutingPolicyFactory, } from './routing-policy.js';
|
|
4
5
|
const logger = getLogger('naylence.fame.sentinel.routing_profile_factory');
|
|
5
6
|
export const PROFILE_NAME_DEVELOPMENT = 'development';
|
|
@@ -34,13 +35,11 @@ const HYBRID_ONLY_PROFILE = {
|
|
|
34
35
|
type: 'HybridPathRoutingPolicy',
|
|
35
36
|
loadBalancingStrategy: { type: 'HRWLoadBalancingStrategy' },
|
|
36
37
|
};
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
[PROFILE_NAME_HYBRID_ONLY]: HYBRID_ONLY_PROFILE,
|
|
43
|
-
};
|
|
38
|
+
registerProfile(ROUTING_POLICY_FACTORY_BASE, PROFILE_NAME_DEVELOPMENT, DEVELOPMENT_PROFILE, { source: 'routing-profile-factory' });
|
|
39
|
+
registerProfile(ROUTING_POLICY_FACTORY_BASE, PROFILE_NAME_PRODUCTION, PRODUCTION_PROFILE, { source: 'routing-profile-factory' });
|
|
40
|
+
registerProfile(ROUTING_POLICY_FACTORY_BASE, PROFILE_NAME_BASIC, BASIC_PROFILE, { source: 'routing-profile-factory' });
|
|
41
|
+
registerProfile(ROUTING_POLICY_FACTORY_BASE, PROFILE_NAME_CAPABILITY_AWARE, CAPABILITY_AWARE_PROFILE, { source: 'routing-profile-factory' });
|
|
42
|
+
registerProfile(ROUTING_POLICY_FACTORY_BASE, PROFILE_NAME_HYBRID_ONLY, HYBRID_ONLY_PROFILE, { source: 'routing-profile-factory' });
|
|
44
43
|
export const FACTORY_META = {
|
|
45
44
|
base: ROUTING_POLICY_FACTORY_BASE,
|
|
46
45
|
key: 'RoutingProfile',
|
|
@@ -95,7 +94,7 @@ export class RoutingProfileFactory extends RoutingPolicyFactory {
|
|
|
95
94
|
return undefined;
|
|
96
95
|
}
|
|
97
96
|
getProfileConfig(profile) {
|
|
98
|
-
const routingConfig =
|
|
97
|
+
const routingConfig = getProfile(ROUTING_POLICY_FACTORY_BASE, profile);
|
|
99
98
|
if (!routingConfig) {
|
|
100
99
|
throw new Error('Unknown routing profile');
|
|
101
100
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createResource, Expressions, } from '@naylence/factory';
|
|
3
3
|
import { StorageProviderFactory, registerStorageProviderFactory, STORAGE_PROVIDER_FACTORY_BASE_TYPE, } from './storage-provider-factory.js';
|
|
4
|
+
import { getProfile, listProfiles, registerProfile, } from '../profile/profile-registry.js';
|
|
4
5
|
const ENV_VAR_STORAGE_DB_DIRECTORY = 'FAME_STORAGE_DB_DIRECTORY';
|
|
5
6
|
const ENV_VAR_STORAGE_MASTER_KEY = 'FAME_STORAGE_MASTER_KEY';
|
|
6
7
|
const ENV_VAR_STORAGE_ENCRYPTED = 'FAME_STORAGE_ENCRYPTED';
|
|
@@ -37,18 +38,13 @@ const ENCRYPTED_SQLITE_PROFILE_CONFIG = {
|
|
|
37
38
|
masterKey: Expressions.env(ENV_VAR_STORAGE_MASTER_KEY),
|
|
38
39
|
isCached: true,
|
|
39
40
|
};
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
[PROFILE_NAME_MEMORY]: MEMORY_PROFILE_CONFIG,
|
|
43
|
-
[PROFILE_NAME_INDEXEDDB]: INDEXEDDB_PROFILE_CONFIG,
|
|
44
|
-
};
|
|
45
|
-
// Extended profile map - can be augmented by Node.js environment
|
|
46
|
-
const PROFILE_MAP = {
|
|
47
|
-
...BASE_PROFILE_MAP,
|
|
48
|
-
};
|
|
41
|
+
registerProfile(STORAGE_PROVIDER_FACTORY_BASE_TYPE, PROFILE_NAME_MEMORY, MEMORY_PROFILE_CONFIG, { source: 'storage-profile-factory' });
|
|
42
|
+
registerProfile(STORAGE_PROVIDER_FACTORY_BASE_TYPE, PROFILE_NAME_INDEXEDDB, INDEXEDDB_PROFILE_CONFIG, { source: 'storage-profile-factory' });
|
|
49
43
|
// Function to register additional profiles (used by Node.js build)
|
|
50
44
|
export function registerStorageProfile(name, config) {
|
|
51
|
-
|
|
45
|
+
registerProfile(STORAGE_PROVIDER_FACTORY_BASE_TYPE, name, config, {
|
|
46
|
+
source: 'storage-profile-factory',
|
|
47
|
+
});
|
|
52
48
|
}
|
|
53
49
|
// Export the SQLite configs so they can be registered from node-index.ts
|
|
54
50
|
export const SQLITE_PROFILES = {
|
|
@@ -67,9 +63,9 @@ export class StorageProfileFactory extends StorageProviderFactory {
|
|
|
67
63
|
type: 'StorageProfile',
|
|
68
64
|
});
|
|
69
65
|
const profileName = (parsed.profile ?? PROFILE_NAME_MEMORY).toLowerCase();
|
|
70
|
-
const profileConfig =
|
|
66
|
+
const profileConfig = getProfile(STORAGE_PROVIDER_FACTORY_BASE_TYPE, profileName);
|
|
71
67
|
if (!profileConfig) {
|
|
72
|
-
throw new Error(`Unknown storage profile '${profileName}'. Supported profiles: ${
|
|
68
|
+
throw new Error(`Unknown storage profile '${profileName}'. Supported profiles: ${listProfiles(STORAGE_PROVIDER_FACTORY_BASE_TYPE).join(', ')}`);
|
|
73
69
|
}
|
|
74
70
|
const createOptions = {
|
|
75
71
|
...options,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Expressions } from '@naylence/factory';
|
|
2
2
|
import { getLogger } from '../util/logging.js';
|
|
3
3
|
import { TRACE_EMITTER_FACTORY_BASE_TYPE, TraceEmitterFactory, } from './trace-emitter-factory.js';
|
|
4
|
+
import { getProfile, registerProfile, } from '../profile/profile-registry.js';
|
|
4
5
|
const logger = getLogger('naylence.fame.telemetry.trace_emitter_profile_factory');
|
|
5
6
|
export const PROFILE_NAME_NOOP = 'noop';
|
|
6
7
|
export const PROFILE_NAME_OPEN_TELEMETRY = 'open-telemetry';
|
|
@@ -13,10 +14,8 @@ const OPEN_TELEMETRY_PROFILE = {
|
|
|
13
14
|
serviceName: Expressions.env(ENV_VAR_TELEMETRY_SERVICE_NAME, 'naylence-service'),
|
|
14
15
|
headers: {},
|
|
15
16
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
[PROFILE_NAME_OPEN_TELEMETRY]: OPEN_TELEMETRY_PROFILE,
|
|
19
|
-
};
|
|
17
|
+
registerProfile(TRACE_EMITTER_FACTORY_BASE_TYPE, PROFILE_NAME_NOOP, NOOP_PROFILE, { source: 'trace-emitter-profile-factory' });
|
|
18
|
+
registerProfile(TRACE_EMITTER_FACTORY_BASE_TYPE, PROFILE_NAME_OPEN_TELEMETRY, OPEN_TELEMETRY_PROFILE, { source: 'trace-emitter-profile-factory' });
|
|
20
19
|
export const FACTORY_META = {
|
|
21
20
|
base: TRACE_EMITTER_FACTORY_BASE_TYPE,
|
|
22
21
|
key: 'TraceEmitterProfile',
|
|
@@ -85,13 +84,10 @@ function canonicalizeProfileName(value) {
|
|
|
85
84
|
return PROFILE_ALIASES[normalized] ?? normalized;
|
|
86
85
|
}
|
|
87
86
|
function resolveProfileConfig(profileName) {
|
|
88
|
-
const profile =
|
|
87
|
+
const profile = getProfile(TRACE_EMITTER_FACTORY_BASE_TYPE, profileName);
|
|
89
88
|
if (!profile) {
|
|
90
89
|
throw new Error(`Unknown trace emitter profile: ${profileName}`);
|
|
91
90
|
}
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
function deepClone(value) {
|
|
95
|
-
return JSON.parse(JSON.stringify(value));
|
|
91
|
+
return profile;
|
|
96
92
|
}
|
|
97
93
|
export default TraceEmitterProfileFactory;
|
|
@@ -14,6 +14,7 @@ export { VERSION } from './version.js';
|
|
|
14
14
|
export * from './naylence/fame/errors/index.js';
|
|
15
15
|
export * from './naylence/fame/util/index.js';
|
|
16
16
|
export * from './naylence/fame/channel/index.js';
|
|
17
|
+
export * from './naylence/fame/profile/index.js';
|
|
17
18
|
// Storage providers that are safe for browsers (in-memory + IndexedDB)
|
|
18
19
|
export * from './naylence/fame/storage/index.js';
|
|
19
20
|
// Node lifecycle and context (Fame "Node" abstraction, not Node.js)
|
package/dist/esm/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file is auto-generated during build - do not edit manually
|
|
2
|
-
// Generated from package.json version: 0.4.
|
|
2
|
+
// Generated from package.json version: 0.4.7
|
|
3
3
|
/**
|
|
4
4
|
* The package version, injected at build time.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.4.
|
|
7
|
+
export const VERSION = '0.4.7';
|