@naylence/runtime 0.3.21 → 0.4.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.
Files changed (85) hide show
  1. package/dist/browser/index.cjs +3144 -1307
  2. package/dist/browser/index.mjs +3116 -1301
  3. package/dist/cjs/naylence/fame/factory-manifest.js +6 -0
  4. package/dist/cjs/naylence/fame/node/node-event-listener.js +4 -0
  5. package/dist/cjs/naylence/fame/security/auth/default-policy-authorizer-factory.js +147 -0
  6. package/dist/cjs/naylence/fame/security/auth/default-policy-authorizer.js +291 -0
  7. package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
  8. package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer.js +19 -4
  9. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-definition.js +60 -0
  10. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-factory.js +35 -0
  11. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-source-factory.js +35 -0
  12. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-source.js +2 -0
  13. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy.js +2 -0
  14. package/dist/cjs/naylence/fame/security/auth/policy/basic-authorization-policy-factory.js +99 -0
  15. package/dist/cjs/naylence/fame/security/auth/policy/basic-authorization-policy.js +449 -0
  16. package/dist/cjs/naylence/fame/security/auth/policy/index.js +40 -0
  17. package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.js +101 -0
  18. package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +164 -0
  19. package/dist/cjs/naylence/fame/security/auth/policy/pattern-matcher.js +195 -0
  20. package/dist/cjs/naylence/fame/security/auth/policy/scope-matcher.js +169 -0
  21. package/dist/cjs/naylence/fame/security/auth/policy-authorizer.js +2 -0
  22. package/dist/cjs/naylence/fame/security/default-security-manager.js +94 -0
  23. package/dist/cjs/naylence/fame/security/index.js +3 -0
  24. package/dist/cjs/naylence/fame/security/node-security-profile-factory.js +3 -1
  25. package/dist/cjs/naylence/fame/sentinel/router.js +67 -1
  26. package/dist/cjs/naylence/fame/sentinel/sentinel.js +46 -2
  27. package/dist/cjs/naylence/fame/util/register-runtime-factories.js +2 -0
  28. package/dist/cjs/version.js +2 -2
  29. package/dist/esm/naylence/fame/factory-manifest.js +6 -0
  30. package/dist/esm/naylence/fame/node/node-event-listener.js +4 -0
  31. package/dist/esm/naylence/fame/security/auth/default-policy-authorizer-factory.js +110 -0
  32. package/dist/esm/naylence/fame/security/auth/default-policy-authorizer.js +287 -0
  33. package/dist/esm/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
  34. package/dist/esm/naylence/fame/security/auth/oauth2-authorizer.js +19 -4
  35. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-definition.js +57 -0
  36. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-factory.js +31 -0
  37. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-source-factory.js +31 -0
  38. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-source.js +1 -0
  39. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy.js +1 -0
  40. package/dist/esm/naylence/fame/security/auth/policy/basic-authorization-policy-factory.js +62 -0
  41. package/dist/esm/naylence/fame/security/auth/policy/basic-authorization-policy.js +445 -0
  42. package/dist/esm/naylence/fame/security/auth/policy/index.js +20 -0
  43. package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.js +64 -0
  44. package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +127 -0
  45. package/dist/esm/naylence/fame/security/auth/policy/pattern-matcher.js +185 -0
  46. package/dist/esm/naylence/fame/security/auth/policy/scope-matcher.js +162 -0
  47. package/dist/esm/naylence/fame/security/auth/policy-authorizer.js +1 -0
  48. package/dist/esm/naylence/fame/security/default-security-manager.js +94 -0
  49. package/dist/esm/naylence/fame/security/index.js +3 -0
  50. package/dist/esm/naylence/fame/security/node-security-profile-factory.js +2 -0
  51. package/dist/esm/naylence/fame/sentinel/router.js +64 -0
  52. package/dist/esm/naylence/fame/sentinel/sentinel.js +47 -3
  53. package/dist/esm/naylence/fame/util/register-runtime-factories.js +2 -0
  54. package/dist/esm/version.js +2 -2
  55. package/dist/node/index.cjs +3140 -1303
  56. package/dist/node/index.mjs +3116 -1301
  57. package/dist/node/node.cjs +3191 -1338
  58. package/dist/node/node.mjs +3167 -1336
  59. package/dist/types/naylence/fame/factory-manifest.d.ts +1 -1
  60. package/dist/types/naylence/fame/node/node-event-listener.d.ts +31 -0
  61. package/dist/types/naylence/fame/security/auth/authorizer.d.ts +37 -0
  62. package/dist/types/naylence/fame/security/auth/default-policy-authorizer-factory.d.ts +55 -0
  63. package/dist/types/naylence/fame/security/auth/default-policy-authorizer.d.ts +99 -0
  64. package/dist/types/naylence/fame/security/auth/oauth2-authorizer-factory.d.ts +2 -0
  65. package/dist/types/naylence/fame/security/auth/oauth2-authorizer.d.ts +2 -0
  66. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-definition.d.ts +166 -0
  67. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-factory.d.ts +38 -0
  68. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-source-factory.d.ts +38 -0
  69. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-source.d.ts +20 -0
  70. package/dist/types/naylence/fame/security/auth/policy/authorization-policy.d.ts +55 -0
  71. package/dist/types/naylence/fame/security/auth/policy/basic-authorization-policy-factory.d.ts +42 -0
  72. package/dist/types/naylence/fame/security/auth/policy/basic-authorization-policy.d.ts +78 -0
  73. package/dist/types/naylence/fame/security/auth/policy/index.d.ts +19 -0
  74. package/dist/types/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.d.ts +51 -0
  75. package/dist/types/naylence/fame/security/auth/policy/local-file-authorization-policy-source.d.ts +67 -0
  76. package/dist/types/naylence/fame/security/auth/policy/pattern-matcher.d.ts +84 -0
  77. package/dist/types/naylence/fame/security/auth/policy/scope-matcher.d.ts +61 -0
  78. package/dist/types/naylence/fame/security/auth/policy-authorizer.d.ts +12 -0
  79. package/dist/types/naylence/fame/security/default-security-manager.d.ts +22 -0
  80. package/dist/types/naylence/fame/security/index.d.ts +2 -0
  81. package/dist/types/naylence/fame/security/node-security-profile-factory.d.ts +1 -0
  82. package/dist/types/naylence/fame/sentinel/router.d.ts +68 -0
  83. package/dist/types/naylence/fame/sentinel/sentinel.d.ts +16 -0
  84. package/dist/types/version.d.ts +1 -1
  85. package/package.json +1 -1
@@ -0,0 +1,287 @@
1
+ import { createAuthorizationContext } from '@naylence/core';
2
+ import { getLogger } from '../../util/logging.js';
3
+ const logger = getLogger('naylence.fame.security.auth.default_policy_authorizer');
4
+ function decodeCredentials(credentials) {
5
+ if (typeof TextDecoder !== 'undefined') {
6
+ return new TextDecoder().decode(credentials);
7
+ }
8
+ if (typeof Buffer !== 'undefined') {
9
+ return Buffer.from(credentials).toString('utf-8');
10
+ }
11
+ throw new Error('Unable to decode credential bytes without TextDecoder support');
12
+ }
13
+ function normalizeToken(credentials) {
14
+ const raw = typeof credentials === 'string'
15
+ ? credentials
16
+ : decodeCredentials(credentials);
17
+ const trimmed = raw.trim();
18
+ if (trimmed.length === 0) {
19
+ return undefined;
20
+ }
21
+ if (trimmed.toLowerCase().startsWith('bearer ')) {
22
+ const candidate = trimmed.slice(7).trim();
23
+ return candidate.length > 0 ? candidate : undefined;
24
+ }
25
+ return trimmed;
26
+ }
27
+ function normalizeOptions(options) {
28
+ if (options === undefined || options === null) {
29
+ return {};
30
+ }
31
+ if (typeof options !== 'object') {
32
+ throw new TypeError('DefaultPolicyAuthorizer options must be an object');
33
+ }
34
+ const candidate = options;
35
+ return {
36
+ tokenVerifier: candidate.tokenVerifier ?? candidate.token_verifier,
37
+ policy: candidate.policy,
38
+ policySource: candidate.policySource ?? candidate.policy_source,
39
+ };
40
+ }
41
+ /**
42
+ * An authorizer that delegates authorization decisions to a pluggable policy.
43
+ *
44
+ * This authorizer combines token-based authentication with policy-based
45
+ * authorization. The token verifier handles authentication (validating
46
+ * credentials), while the authorization policy handles authorization
47
+ * decisions (allow/deny based on the request context).
48
+ */
49
+ export class DefaultPolicyAuthorizer {
50
+ constructor(options = {}) {
51
+ this.policyLoaded = false;
52
+ const normalized = normalizeOptions(options);
53
+ if (normalized.tokenVerifier) {
54
+ this.tokenVerifierImpl = normalized.tokenVerifier;
55
+ }
56
+ if (normalized.policy) {
57
+ this.policyImpl = normalized.policy;
58
+ this.policyLoaded = true;
59
+ }
60
+ if (normalized.policySource) {
61
+ this.policySource = normalized.policySource;
62
+ }
63
+ // Validate that we have either a policy or a policy source
64
+ if (!normalized.policy && !normalized.policySource) {
65
+ throw new Error('DefaultPolicyAuthorizer requires either a policy or a policySource');
66
+ }
67
+ }
68
+ /**
69
+ * The currently active authorization policy.
70
+ */
71
+ get policy() {
72
+ if (!this.policyImpl) {
73
+ throw new Error('Authorization policy not loaded. Call ensurePolicyLoaded() first.');
74
+ }
75
+ return this.policyImpl;
76
+ }
77
+ /**
78
+ * The token verifier used for authentication.
79
+ */
80
+ get tokenVerifier() {
81
+ if (!this.tokenVerifierImpl) {
82
+ throw new Error('DefaultPolicyAuthorizer is not initialized properly, missing tokenVerifier');
83
+ }
84
+ return this.tokenVerifierImpl;
85
+ }
86
+ set tokenVerifier(verifier) {
87
+ this.tokenVerifierImpl = verifier;
88
+ }
89
+ /**
90
+ * Ensures the authorization policy is loaded.
91
+ * If using a policy source, loads the policy from it.
92
+ */
93
+ async ensurePolicyLoaded() {
94
+ if (this.policyLoaded && this.policyImpl) {
95
+ return;
96
+ }
97
+ if (!this.policySource) {
98
+ throw new Error('No policy source configured and no policy provided');
99
+ }
100
+ logger.debug('loading_policy_from_source');
101
+ this.policyImpl = await this.policySource.loadPolicy();
102
+ this.policyLoaded = true;
103
+ logger.info('policy_loaded_from_source');
104
+ }
105
+ /**
106
+ * Reloads the authorization policy from the policy source.
107
+ * Only works if a policy source was configured.
108
+ */
109
+ async reloadPolicy() {
110
+ if (!this.policySource) {
111
+ throw new Error('Cannot reload policy: no policy source configured');
112
+ }
113
+ logger.debug('reloading_policy_from_source');
114
+ this.policyImpl = await this.policySource.loadPolicy();
115
+ this.policyLoaded = true;
116
+ logger.info('policy_reloaded_from_source');
117
+ }
118
+ /**
119
+ * Authenticates credentials and returns an authorization context.
120
+ *
121
+ * @param credentials - The credentials to authenticate (token string or bytes)
122
+ * @returns The authorization context if authentication succeeds, undefined otherwise
123
+ */
124
+ async authenticate(credentials) {
125
+ const token = normalizeToken(credentials);
126
+ if (!token) {
127
+ return undefined;
128
+ }
129
+ try {
130
+ const verifier = this.tokenVerifier;
131
+ const context = await verifier.verify(token);
132
+ return createAuthorizationContext({
133
+ ...context,
134
+ authenticated: true,
135
+ authorized: false, // Authorization happens in authorize()
136
+ authMethod: context.authMethod ?? 'jwt',
137
+ });
138
+ }
139
+ catch (error) {
140
+ logger.warning('token_verification_failed', {
141
+ error: error instanceof Error ? error.message : String(error),
142
+ });
143
+ return undefined;
144
+ }
145
+ }
146
+ /**
147
+ * Authorizes a request using the configured authorization policy.
148
+ *
149
+ * For NodeAttach frames, evaluates policy with action='Connect'.
150
+ * For other frames, this method performs basic authentication validation
151
+ * but does NOT infer send/receive actions. Route-level authorization
152
+ * is handled separately via authorizeRoute().
153
+ *
154
+ * @param node - The node handling the request
155
+ * @param envelope - The FAME envelope being authorized
156
+ * @param context - Optional delivery context
157
+ * @returns The authorization context if authorized, undefined if denied
158
+ */
159
+ async authorize(node, envelope, context) {
160
+ const authorization = context?.security?.authorization;
161
+ // Must be authenticated first
162
+ if (!authorization || !authorization.authenticated) {
163
+ logger.debug('authorization_denied_not_authenticated');
164
+ return undefined;
165
+ }
166
+ // Ensure policy is loaded
167
+ await this.ensurePolicyLoaded();
168
+ // For NodeAttach frames, evaluate policy with 'Connect' action
169
+ const frameType = envelope.frame?.type;
170
+ if (frameType === 'NodeAttach') {
171
+ let decision;
172
+ try {
173
+ decision = await this.policy.evaluateRequest(node, envelope, context, 'Connect');
174
+ }
175
+ catch (error) {
176
+ logger.error('policy_evaluation_failed', {
177
+ error: error instanceof Error ? error.message : String(error),
178
+ action: 'Connect',
179
+ });
180
+ return undefined;
181
+ }
182
+ if (decision.effect === 'allow') {
183
+ logger.debug('authorization_allowed', {
184
+ matchedRule: decision.matchedRule,
185
+ reason: decision.reason,
186
+ action: 'Connect',
187
+ });
188
+ return createAuthorizationContext({
189
+ ...authorization,
190
+ authorized: true,
191
+ authMethod: authorization.authMethod ?? 'policy',
192
+ });
193
+ }
194
+ else {
195
+ logger.debug('authorization_denied', {
196
+ matchedRule: decision.matchedRule,
197
+ reason: decision.reason,
198
+ action: 'Connect',
199
+ });
200
+ return undefined;
201
+ }
202
+ }
203
+ // For non-NodeAttach frames, authentication is sufficient at this stage.
204
+ // Route-level authorization is performed via authorizeRoute() after
205
+ // the routing decision is made.
206
+ logger.debug('authorization_passed_authentication_only', {
207
+ envp_id: envelope.id,
208
+ frame_type: frameType,
209
+ });
210
+ return createAuthorizationContext({
211
+ ...authorization,
212
+ authorized: true,
213
+ authMethod: authorization.authMethod ?? 'policy',
214
+ });
215
+ }
216
+ /**
217
+ * Authorizes a routing action after the routing decision has been made.
218
+ *
219
+ * This method evaluates the authorization policy with the explicitly
220
+ * provided action token (ForwardUpstream, ForwardDownstream, ForwardPeer,
221
+ * DeliverLocal).
222
+ *
223
+ * @param node - The node handling the request
224
+ * @param envelope - The FAME envelope being routed
225
+ * @param action - The authorization action token from the routing decision
226
+ * @param context - Optional delivery context
227
+ * @returns RouteAuthorizationResult with authorization decision
228
+ */
229
+ async authorizeRoute(node, envelope, action, context) {
230
+ const authorization = context?.security?.authorization;
231
+ // If not authenticated, deny route authorization
232
+ if (!authorization || !authorization.authenticated) {
233
+ logger.debug('route_authorization_denied_not_authenticated', {
234
+ action,
235
+ });
236
+ return {
237
+ authorized: false,
238
+ denialReason: 'not_authenticated',
239
+ };
240
+ }
241
+ // Ensure policy is loaded
242
+ await this.ensurePolicyLoaded();
243
+ // Evaluate the policy with the provided action
244
+ let decision;
245
+ try {
246
+ decision = await this.policy.evaluateRequest(node, envelope, context, action);
247
+ }
248
+ catch (error) {
249
+ logger.error('route_policy_evaluation_failed', {
250
+ error: error instanceof Error ? error.message : String(error),
251
+ action,
252
+ });
253
+ return {
254
+ authorized: false,
255
+ denialReason: 'policy_evaluation_error',
256
+ };
257
+ }
258
+ if (decision.effect === 'allow') {
259
+ logger.debug('route_authorization_allowed', {
260
+ matchedRule: decision.matchedRule,
261
+ reason: decision.reason,
262
+ action,
263
+ });
264
+ return {
265
+ authorized: true,
266
+ authContext: createAuthorizationContext({
267
+ ...authorization,
268
+ authorized: true,
269
+ authMethod: authorization.authMethod ?? 'policy',
270
+ }),
271
+ matchedRule: decision.matchedRule,
272
+ };
273
+ }
274
+ else {
275
+ logger.debug('route_authorization_denied', {
276
+ matchedRule: decision.matchedRule,
277
+ reason: decision.reason,
278
+ action,
279
+ });
280
+ return {
281
+ authorized: false,
282
+ denialReason: decision.reason ?? 'policy_denied',
283
+ matchedRule: decision.matchedRule,
284
+ };
285
+ }
286
+ }
287
+ }
@@ -51,6 +51,7 @@ export class OAuth2AuthorizerFactory extends AuthorizerFactory {
51
51
  maxTtlSec: normalized.maxTtlSec,
52
52
  reverseAuthTtlSec: normalized.reverseAuthTtlSec,
53
53
  enforceTokenSubjectNodeIdentity: normalized.enforceTokenSubjectNodeIdentity,
54
+ trustedClientScope: normalized.trustedClientScope,
54
55
  };
55
56
  if (tokenIssuer) {
56
57
  authorizerOptions.tokenIssuer = tokenIssuer;
@@ -120,6 +121,11 @@ function normalizeConfig(config) {
120
121
  : DEFAULT_REVERSE_AUTH_TTL_SEC;
121
122
  const enforceTokenSubjectNodeIdentity = normalizeBooleanOption(source.enforceTokenSubjectNodeIdentity ??
122
123
  source.enforce_token_subject_node_identity, false);
124
+ const trustedClientScope = typeof source.trustedClientScope === 'string'
125
+ ? source.trustedClientScope
126
+ : typeof source.trusted_client_scope === 'string'
127
+ ? source.trusted_client_scope
128
+ : undefined;
123
129
  const tokenVerifierConfigInput = source.tokenVerifierConfig ?? source.token_verifier_config ?? null;
124
130
  const tokenVerifierConfig = normalizeTokenVerifierConfig({
125
131
  config: tokenVerifierConfigInput,
@@ -140,6 +146,7 @@ function normalizeConfig(config) {
140
146
  reverseAuthTtlSec: reverseAuthCandidate,
141
147
  enforceTokenSubjectNodeIdentity,
142
148
  ...(audience ? { audience } : {}),
149
+ ...(trustedClientScope ? { trustedClientScope } : {}),
143
150
  };
144
151
  if (tokenIssuerConfig) {
145
152
  normalized.tokenIssuerConfig = tokenIssuerConfig;
@@ -38,6 +38,10 @@ function normalizeOptions(raw) {
38
38
  (typeof snake.enforce_token_subject_node_identity === 'boolean'
39
39
  ? snake.enforce_token_subject_node_identity
40
40
  : undefined);
41
+ const trustedClientScope = camel.trustedClientScope ??
42
+ (typeof snake.trusted_client_scope === 'string'
43
+ ? snake.trusted_client_scope
44
+ : undefined);
41
45
  return {
42
46
  tokenVerifier,
43
47
  tokenIssuer,
@@ -48,6 +52,7 @@ function normalizeOptions(raw) {
48
52
  maxTtlSec,
49
53
  reverseAuthTtlSec,
50
54
  enforceTokenSubjectNodeIdentity,
55
+ trustedClientScope,
51
56
  };
52
57
  }
53
58
  export class OAuth2Authorizer {
@@ -63,6 +68,7 @@ export class OAuth2Authorizer {
63
68
  options.reverseAuthTtlSec ?? DEFAULT_REVERSE_AUTH_TTL_SEC;
64
69
  this.enforceTokenSubjectNodeIdentity =
65
70
  options.enforceTokenSubjectNodeIdentity ?? false;
71
+ this.trustedClientScope = options.trustedClientScope ?? 'node.trusted';
66
72
  }
67
73
  get tokenVerifier() {
68
74
  return this.tokenVerifierImpl;
@@ -192,11 +198,20 @@ export class OAuth2Authorizer {
192
198
  });
193
199
  return undefined;
194
200
  }
195
- // Enforce token subject node identity if enabled
201
+ // Enforce token subject node identity if enabled and not a trusted client
196
202
  if (this.enforceTokenSubjectNodeIdentity) {
197
- const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
198
- if (!validationResult) {
199
- return undefined;
203
+ const isTrustedClient = scopes.has(this.trustedClientScope);
204
+ if (isTrustedClient) {
205
+ logger.debug('oauth2_attach_trusted_client_bypass', {
206
+ system_id: frame.systemId,
207
+ trusted_scope: this.trustedClientScope,
208
+ });
209
+ }
210
+ else {
211
+ const validationResult = await this.validateTokenSubjectNodeIdentity(frame.systemId, claims);
212
+ if (!validationResult) {
213
+ return undefined;
214
+ }
200
215
  }
201
216
  }
202
217
  claims.instance_id = claims.instance_id ?? frame.instanceId;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Authorization policy definition types.
3
+ *
4
+ * This module defines the schema for authorization policies that can be
5
+ * loaded from YAML/JSON files and evaluated at runtime.
6
+ */
7
+ /**
8
+ * Maximum nesting depth for scope requirements.
9
+ */
10
+ export const MAX_SCOPE_NESTING_DEPTH = 5;
11
+ /**
12
+ * Known fields in AuthorizationPolicyDefinition.
13
+ */
14
+ export const KNOWN_POLICY_FIELDS = new Set([
15
+ 'version',
16
+ 'default_effect',
17
+ 'rules',
18
+ ]);
19
+ /**
20
+ * Known fields in AuthorizationRuleDefinition.
21
+ * Fields not in this set trigger a warning.
22
+ */
23
+ export const KNOWN_RULE_FIELDS = new Set([
24
+ 'id',
25
+ 'description',
26
+ 'effect',
27
+ 'action',
28
+ 'address',
29
+ 'frame_type',
30
+ 'origin_type',
31
+ 'scope',
32
+ 'when', // Reserved for advanced-security
33
+ ]);
34
+ /**
35
+ * Valid action values.
36
+ */
37
+ export const VALID_ACTIONS = [
38
+ 'Connect',
39
+ 'ForwardUpstream',
40
+ 'ForwardDownstream',
41
+ 'ForwardPeer',
42
+ 'DeliverLocal',
43
+ '*',
44
+ ];
45
+ /**
46
+ * Valid origin type values (lowercase, matching DeliveryOriginType string values).
47
+ */
48
+ export const VALID_ORIGIN_TYPES = [
49
+ 'downstream',
50
+ 'upstream',
51
+ 'peer',
52
+ 'local',
53
+ ];
54
+ /**
55
+ * Valid effect values.
56
+ */
57
+ export const VALID_EFFECTS = ['allow', 'deny'];
@@ -0,0 +1,31 @@
1
+ import { AbstractResourceFactory, createDefaultResource, createResource, } from '@naylence/factory';
2
+ /**
3
+ * Base type identifier for authorization policy factories.
4
+ */
5
+ export const AUTHORIZATION_POLICY_FACTORY_BASE_TYPE = 'AuthorizationPolicyFactory';
6
+ /**
7
+ * Abstract factory base class for creating authorization policies.
8
+ *
9
+ * Implementations of this factory create specific types of authorization
10
+ * policies (e.g., expression-based, rule-based, etc.).
11
+ */
12
+ export class AuthorizationPolicyFactory extends AbstractResourceFactory {
13
+ /**
14
+ * Static helper to create an authorization policy using the factory registry.
15
+ *
16
+ * @param config - Configuration for the policy
17
+ * @param options - Resource creation options
18
+ * @returns The created policy, or undefined if no factory matched
19
+ */
20
+ static async createAuthorizationPolicy(config, options = {}) {
21
+ if (config) {
22
+ const policy = await createResource(AUTHORIZATION_POLICY_FACTORY_BASE_TYPE, config, options);
23
+ if (!policy) {
24
+ throw new Error('Failed to create authorization policy from configuration');
25
+ }
26
+ return policy;
27
+ }
28
+ const policy = await createDefaultResource(AUTHORIZATION_POLICY_FACTORY_BASE_TYPE, null, options);
29
+ return policy ?? undefined;
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ import { AbstractResourceFactory, createDefaultResource, createResource, } from '@naylence/factory';
2
+ /**
3
+ * Base type identifier for authorization policy source factories.
4
+ */
5
+ export const AUTHORIZATION_POLICY_SOURCE_FACTORY_BASE_TYPE = 'AuthorizationPolicySourceFactory';
6
+ /**
7
+ * Abstract factory base class for creating authorization policy sources.
8
+ *
9
+ * Implementations of this factory create specific types of policy sources
10
+ * (e.g., local file, remote store, in-memory, etc.).
11
+ */
12
+ export class AuthorizationPolicySourceFactory extends AbstractResourceFactory {
13
+ /**
14
+ * Static helper to create an authorization policy source using the factory registry.
15
+ *
16
+ * @param config - Configuration for the policy source
17
+ * @param options - Resource creation options
18
+ * @returns The created policy source, or undefined if no factory matched
19
+ */
20
+ static async createAuthorizationPolicySource(config, options = {}) {
21
+ if (config) {
22
+ const source = await createResource(AUTHORIZATION_POLICY_SOURCE_FACTORY_BASE_TYPE, config, options);
23
+ if (!source) {
24
+ throw new Error('Failed to create authorization policy source from configuration');
25
+ }
26
+ return source;
27
+ }
28
+ const source = await createDefaultResource(AUTHORIZATION_POLICY_SOURCE_FACTORY_BASE_TYPE, null, options);
29
+ return source ?? undefined;
30
+ }
31
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Factory for creating BasicAuthorizationPolicy instances.
3
+ */
4
+ import { AUTHORIZATION_POLICY_FACTORY_BASE_TYPE, AuthorizationPolicyFactory, } from './authorization-policy-factory.js';
5
+ /**
6
+ * Lazy import for tree-shaking.
7
+ */
8
+ async function safeImportModule() {
9
+ return await import('./basic-authorization-policy.js');
10
+ }
11
+ function normalizeConfig(config) {
12
+ if (!config) {
13
+ throw new Error('BasicAuthorizationPolicyFactory requires a configuration with a policyDefinition');
14
+ }
15
+ const candidate = config;
16
+ // Support both camelCase and snake_case for policyDefinition
17
+ const policyDefinition = (candidate.policyDefinition ??
18
+ candidate.policy_definition);
19
+ if (!policyDefinition || typeof policyDefinition !== 'object') {
20
+ throw new Error('BasicAuthorizationPolicyConfig requires a policyDefinition object');
21
+ }
22
+ // Support both camelCase and snake_case for warnOnUnknownFields
23
+ const warnOnUnknownFields = candidate.warnOnUnknownFields ?? candidate.warn_on_unknown_fields;
24
+ if (warnOnUnknownFields !== undefined && typeof warnOnUnknownFields !== 'boolean') {
25
+ throw new Error('warnOnUnknownFields must be a boolean');
26
+ }
27
+ return {
28
+ policyDefinition,
29
+ warnOnUnknownFields: warnOnUnknownFields ?? true,
30
+ };
31
+ }
32
+ /**
33
+ * Factory metadata for registration.
34
+ */
35
+ export const FACTORY_META = {
36
+ base: AUTHORIZATION_POLICY_FACTORY_BASE_TYPE,
37
+ key: 'BasicAuthorizationPolicy',
38
+ };
39
+ /**
40
+ * Factory for creating BasicAuthorizationPolicy instances.
41
+ */
42
+ export class BasicAuthorizationPolicyFactory extends AuthorizationPolicyFactory {
43
+ constructor() {
44
+ super(...arguments);
45
+ this.type = 'BasicAuthorizationPolicy';
46
+ }
47
+ /**
48
+ * Creates a BasicAuthorizationPolicy from the given configuration.
49
+ *
50
+ * @param config - Configuration with policyDefinition
51
+ * @returns The created authorization policy
52
+ */
53
+ async create(config) {
54
+ const normalized = normalizeConfig(config);
55
+ const { BasicAuthorizationPolicy } = await safeImportModule();
56
+ return new BasicAuthorizationPolicy({
57
+ policyDefinition: normalized.policyDefinition,
58
+ warnOnUnknownFields: normalized.warnOnUnknownFields,
59
+ });
60
+ }
61
+ }
62
+ export default BasicAuthorizationPolicyFactory;