@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.
Files changed (42) hide show
  1. package/dist/browser/index.cjs +179 -127
  2. package/dist/browser/index.mjs +177 -129
  3. package/dist/cjs/naylence/fame/delivery/delivery-profile-factory.js +5 -9
  4. package/dist/cjs/naylence/fame/index.js +1 -0
  5. package/dist/cjs/naylence/fame/node/admission/admission-profile-factory.js +15 -19
  6. package/dist/cjs/naylence/fame/node/node-identity-policy-profile-factory.js +6 -10
  7. package/dist/cjs/naylence/fame/profile/index.js +8 -0
  8. package/dist/cjs/naylence/fame/profile/profile-registry.js +57 -0
  9. package/dist/cjs/naylence/fame/security/auth/authorization-profile-factory.js +64 -30
  10. package/dist/cjs/naylence/fame/security/default-security-manager-factory.js +4 -3
  11. package/dist/cjs/naylence/fame/security/node-security-profile-factory.js +9 -13
  12. package/dist/cjs/naylence/fame/sentinel/load-balancing/load-balancing-profile-factory.js +10 -13
  13. package/dist/cjs/naylence/fame/sentinel/routing-profile-factory.js +7 -8
  14. package/dist/cjs/naylence/fame/storage/storage-profile-factory.js +8 -12
  15. package/dist/cjs/naylence/fame/telemetry/trace-emitter-profile-factory.js +5 -9
  16. package/dist/cjs/runtime-isomorphic.js +1 -0
  17. package/dist/cjs/version.js +2 -2
  18. package/dist/esm/naylence/fame/delivery/delivery-profile-factory.js +5 -9
  19. package/dist/esm/naylence/fame/index.js +1 -0
  20. package/dist/esm/naylence/fame/node/admission/admission-profile-factory.js +15 -19
  21. package/dist/esm/naylence/fame/node/node-identity-policy-profile-factory.js +6 -10
  22. package/dist/esm/naylence/fame/profile/index.js +1 -0
  23. package/dist/esm/naylence/fame/profile/profile-registry.js +51 -0
  24. package/dist/esm/naylence/fame/security/auth/authorization-profile-factory.js +65 -31
  25. package/dist/esm/naylence/fame/security/default-security-manager-factory.js +4 -3
  26. package/dist/esm/naylence/fame/security/node-security-profile-factory.js +9 -13
  27. package/dist/esm/naylence/fame/sentinel/load-balancing/load-balancing-profile-factory.js +10 -13
  28. package/dist/esm/naylence/fame/sentinel/routing-profile-factory.js +7 -8
  29. package/dist/esm/naylence/fame/storage/storage-profile-factory.js +8 -12
  30. package/dist/esm/naylence/fame/telemetry/trace-emitter-profile-factory.js +5 -9
  31. package/dist/esm/runtime-isomorphic.js +1 -0
  32. package/dist/esm/version.js +2 -2
  33. package/dist/node/index.cjs +179 -127
  34. package/dist/node/index.mjs +177 -129
  35. package/dist/node/node.cjs +182 -128
  36. package/dist/node/node.mjs +180 -130
  37. package/dist/types/naylence/fame/index.d.ts +1 -0
  38. package/dist/types/naylence/fame/profile/index.d.ts +2 -0
  39. package/dist/types/naylence/fame/profile/profile-registry.d.ts +9 -0
  40. package/dist/types/runtime-isomorphic.d.ts +1 -0
  41. package/dist/types/version.d.ts +1 -1
  42. 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
- const PROFILE_MAP = {
215
- [PROFILE_NAME_WELCOME]: WELCOME_SERVICE_PROFILE,
216
- [PROFILE_NAME_WELCOME_PKCE]: WELCOME_SERVICE_PKCE_PROFILE,
217
- [PROFILE_NAME_WELCOME_PKCE_ALIAS]: WELCOME_SERVICE_PKCE_PROFILE,
218
- [PROFILE_NAME_DIRECT]: DIRECT_PROFILE,
219
- [PROFILE_NAME_DIRECT_PKCE]: DIRECT_PKCE_PROFILE,
220
- [PROFILE_NAME_DIRECT_PKCE_ALIAS]: DIRECT_PKCE_PROFILE,
221
- [PROFILE_NAME_DIRECT_HTTP]: DIRECT_HTTP_PROFILE,
222
- [PROFILE_NAME_DIRECT_INPAGE]: DIRECT_INPAGE_PROFILE,
223
- [PROFILE_NAME_DIRECT_INPAGE_ALIAS]: DIRECT_INPAGE_PROFILE,
224
- [PROFILE_NAME_OPEN]: OPEN_PROFILE,
225
- [PROFILE_NAME_NOOP]: NOOP_PROFILE,
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 = PROFILE_MAP[profileName];
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 deepClone(profile);
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
- const PROFILE_MAP = {
14
- [PROFILE_NAME_DEFAULT]: DEFAULT_PROFILE,
15
- [PROFILE_NAME_TOKEN_SUBJECT]: TOKEN_SUBJECT_PROFILE,
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 = PROFILE_MAP[profileName];
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 deepClone(profile);
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, ExpressionEvaluator } from '@naylence/factory';
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: DEFAULT_VERIFIER_CONFIG,
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
- const PROFILE_MAP = {
87
- [PROFILE_NAME_DEFAULT]: DEFAULT_PROFILE,
88
- [PROFILE_NAME_OAUTH2]: OAUTH2_PROFILE,
89
- [PROFILE_NAME_OAUTH2_GATED]: OAUTH2_GATED_PROFILE,
90
- [PROFILE_NAME_OAUTH2_CALLBACK]: OAUTH2_CALLBACK_PROFILE,
91
- [PROFILE_NAME_POLICY_LOCALFILE]: POLICY_LOCALFILE_PROFILE,
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
- const authorizer = await AuthorizerFactory.createAuthorizer(profileConfig, { factoryArgs });
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
- let direct = coerceProfileString(candidate.profile);
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
- let legacyValue = coerceProfileString(candidate[legacyKey]);
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 = PROFILE_MAP[profileName];
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 deepClone(profile);
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
- const PROFILE_MAP = {
272
- [PROFILE_NAME_OVERLAY]: OVERLAY_PROFILE,
273
- [PROFILE_NAME_OVERLAY_CALLBACK]: OVERLAY_CALLBACK_PROFILE,
274
- [PROFILE_NAME_STRICT_OVERLAY]: STRICT_OVERLAY_PROFILE,
275
- [PROFILE_NAME_GATED]: GATED_PROFILE,
276
- [PROFILE_NAME_GATED_CALLBACK]: GATED_CALLBACK_PROFILE,
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 = PROFILE_MAP[profileName];
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 deepClone(template);
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
- switch (profile) {
81
- case PROFILE_NAME_RANDOM:
82
- return RANDOM_PROFILE;
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
- const PROFILE_MAP = {
38
- [PROFILE_NAME_DEVELOPMENT]: DEVELOPMENT_PROFILE,
39
- [PROFILE_NAME_PRODUCTION]: PRODUCTION_PROFILE,
40
- [PROFILE_NAME_BASIC]: BASIC_PROFILE,
41
- [PROFILE_NAME_CAPABILITY_AWARE]: CAPABILITY_AWARE_PROFILE,
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 = PROFILE_MAP[profile];
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
- // Base profile map with browser-safe options
41
- const BASE_PROFILE_MAP = {
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
- PROFILE_MAP[name] = config;
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 = PROFILE_MAP[profileName];
66
+ const profileConfig = getProfile(STORAGE_PROVIDER_FACTORY_BASE_TYPE, profileName);
71
67
  if (!profileConfig) {
72
- throw new Error(`Unknown storage profile '${profileName}'. Supported profiles: ${Object.keys(PROFILE_MAP).join(', ')}`);
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
- const PROFILE_MAP = {
17
- [PROFILE_NAME_NOOP]: NOOP_PROFILE,
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 = PROFILE_MAP[profileName];
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 deepClone(profile);
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)
@@ -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.5
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.5';
7
+ export const VERSION = '0.4.7';