@naylence/runtime 0.4.2 → 0.4.4

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.
@@ -14,12 +14,12 @@ var fastify = require('fastify');
14
14
  var websocketPlugin = require('@fastify/websocket');
15
15
 
16
16
  // This file is auto-generated during build - do not edit manually
17
- // Generated from package.json version: 0.4.2
17
+ // Generated from package.json version: 0.4.4
18
18
  /**
19
19
  * The package version, injected at build time.
20
20
  * @internal
21
21
  */
22
- const VERSION = '0.4.2';
22
+ const VERSION = '0.4.4';
23
23
 
24
24
  /**
25
25
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -21813,6 +21813,7 @@ const PROFILE_NAME_DEFAULT = 'jwt';
21813
21813
  const PROFILE_NAME_OAUTH2 = 'oauth2';
21814
21814
  const PROFILE_NAME_OAUTH2_GATED = 'oauth2-gated';
21815
21815
  const PROFILE_NAME_OAUTH2_CALLBACK = 'oauth2-callback';
21816
+ const PROFILE_NAME_POLICY_LOCALFILE = 'policy-localfile';
21816
21817
  const PROFILE_NAME_NOOP$2 = 'noop';
21817
21818
  const ENV_VAR_JWT_TRUSTED_ISSUER$1 = 'FAME_JWT_TRUSTED_ISSUER';
21818
21819
  const ENV_VAR_JWT_ALGORITHM$1 = 'FAME_JWT_ALGORITHM';
@@ -21820,18 +21821,21 @@ const ENV_VAR_JWT_AUDIENCE$2 = 'FAME_JWT_AUDIENCE';
21820
21821
  const ENV_VAR_JWKS_URL$1 = 'FAME_JWKS_URL';
21821
21822
  const ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY$1 = 'FAME_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY';
21822
21823
  const ENV_VAR_TRUSTED_CLIENT_SCOPE$1 = 'FAME_TRUSTED_CLIENT_SCOPE';
21824
+ const ENV_VAR_AUTH_POLICY_PATH = 'FAME_AUTH_POLICY_PATH';
21825
+ const ENV_VAR_AUTH_POLICY_FORMAT = 'FAME_AUTH_POLICY_FORMAT';
21823
21826
  const ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER$1 = 'FAME_JWT_REVERSE_AUTH_TRUSTED_ISSUER';
21824
21827
  const ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE$1 = 'FAME_JWT_REVERSE_AUTH_AUDIENCE';
21825
21828
  const ENV_VAR_HMAC_SECRET$1 = 'FAME_HMAC_SECRET';
21826
21829
  const DEFAULT_REVERSE_AUTH_ISSUER = 'reverse-auth.naylence.ai';
21827
21830
  const DEFAULT_REVERSE_AUTH_AUDIENCE = 'dev.naylence.ai';
21831
+ const DEFAULT_VERIFIER_CONFIG = {
21832
+ type: 'JWKSJWTTokenVerifier',
21833
+ jwks_url: factory.Expressions.env(ENV_VAR_JWKS_URL$1),
21834
+ issuer: factory.Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER$1),
21835
+ };
21828
21836
  const DEFAULT_PROFILE = {
21829
21837
  type: 'DefaultAuthorizer',
21830
- verifier: {
21831
- type: 'JWKSJWTTokenVerifier',
21832
- jwks_url: factory.Expressions.env(ENV_VAR_JWKS_URL$1),
21833
- issuer: factory.Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER$1),
21834
- },
21838
+ verifier: DEFAULT_VERIFIER_CONFIG,
21835
21839
  };
21836
21840
  const OAUTH2_PROFILE = {
21837
21841
  type: 'OAuth2Authorizer',
@@ -21876,11 +21880,22 @@ const OAUTH2_CALLBACK_PROFILE = {
21876
21880
  const NOOP_PROFILE$2 = {
21877
21881
  type: 'NoopAuthorizer',
21878
21882
  };
21883
+ const DEFAULT_POLICY_SOURCE = {
21884
+ type: 'LocalFileAuthorizationPolicySource',
21885
+ path: factory.Expressions.env(ENV_VAR_AUTH_POLICY_PATH, './auth-policy.yaml'),
21886
+ format: factory.Expressions.env(ENV_VAR_AUTH_POLICY_FORMAT, 'auto'),
21887
+ };
21888
+ const POLICY_LOCALFILE_PROFILE = {
21889
+ type: 'PolicyAuthorizer',
21890
+ verifier: DEFAULT_VERIFIER_CONFIG,
21891
+ policySource: DEFAULT_POLICY_SOURCE,
21892
+ };
21879
21893
  const PROFILE_MAP$5 = {
21880
21894
  [PROFILE_NAME_DEFAULT]: DEFAULT_PROFILE,
21881
21895
  [PROFILE_NAME_OAUTH2]: OAUTH2_PROFILE,
21882
21896
  [PROFILE_NAME_OAUTH2_GATED]: OAUTH2_GATED_PROFILE,
21883
21897
  [PROFILE_NAME_OAUTH2_CALLBACK]: OAUTH2_CALLBACK_PROFILE,
21898
+ [PROFILE_NAME_POLICY_LOCALFILE]: POLICY_LOCALFILE_PROFILE,
21884
21899
  [PROFILE_NAME_NOOP$2]: NOOP_PROFILE$2,
21885
21900
  };
21886
21901
  const PROFILE_ALIASES$1 = {
@@ -21894,6 +21909,9 @@ const PROFILE_ALIASES$1 = {
21894
21909
  'oauth2-callback': PROFILE_NAME_OAUTH2_CALLBACK,
21895
21910
  oauth2_callback: PROFILE_NAME_OAUTH2_CALLBACK,
21896
21911
  'reverse-auth': PROFILE_NAME_OAUTH2_CALLBACK,
21912
+ policy: PROFILE_NAME_POLICY_LOCALFILE,
21913
+ 'policy-localfile': PROFILE_NAME_POLICY_LOCALFILE,
21914
+ policy_localfile: PROFILE_NAME_POLICY_LOCALFILE,
21897
21915
  noop: PROFILE_NAME_NOOP$2,
21898
21916
  'no-op': PROFILE_NAME_NOOP$2,
21899
21917
  no_op: PROFILE_NAME_NOOP$2,
@@ -21969,6 +21987,8 @@ function deepClone$4(value) {
21969
21987
  var authorizationProfileFactory = /*#__PURE__*/Object.freeze({
21970
21988
  __proto__: null,
21971
21989
  AuthorizationProfileFactory: AuthorizationProfileFactory,
21990
+ ENV_VAR_AUTH_POLICY_FORMAT: ENV_VAR_AUTH_POLICY_FORMAT,
21991
+ ENV_VAR_AUTH_POLICY_PATH: ENV_VAR_AUTH_POLICY_PATH,
21972
21992
  ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY: ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY$1,
21973
21993
  ENV_VAR_HMAC_SECRET: ENV_VAR_HMAC_SECRET$1,
21974
21994
  ENV_VAR_JWKS_URL: ENV_VAR_JWKS_URL$1,
@@ -21984,6 +22004,7 @@ var authorizationProfileFactory = /*#__PURE__*/Object.freeze({
21984
22004
  PROFILE_NAME_OAUTH2: PROFILE_NAME_OAUTH2,
21985
22005
  PROFILE_NAME_OAUTH2_CALLBACK: PROFILE_NAME_OAUTH2_CALLBACK,
21986
22006
  PROFILE_NAME_OAUTH2_GATED: PROFILE_NAME_OAUTH2_GATED,
22007
+ PROFILE_NAME_POLICY_LOCALFILE: PROFILE_NAME_POLICY_LOCALFILE,
21987
22008
  default: AuthorizationProfileFactory
21988
22009
  });
21989
22010
 
@@ -22542,6 +22563,7 @@ class BasicAuthorizationPolicy {
22542
22563
  // Action must be explicitly provided; default to wildcard if omitted
22543
22564
  // for backward compatibility during transition
22544
22565
  const resolvedAction = action ?? '*';
22566
+ const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
22545
22567
  const address = extractAddress(envelope);
22546
22568
  const grantedScopes = extractGrantedScopes(context);
22547
22569
  const rawFrameType = envelope.frame
@@ -22551,8 +22573,8 @@ class BasicAuthorizationPolicy {
22551
22573
  : '';
22552
22574
  // Extract and normalize origin type for rule matching
22553
22575
  const rawOriginType = context?.originType;
22554
- const originTypeNormalized = typeof rawOriginType === 'string' && rawOriginType.trim().length > 0
22555
- ? rawOriginType.trim().toLowerCase()
22576
+ const originTypeNormalized = typeof rawOriginType === 'string'
22577
+ ? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
22556
22578
  : undefined;
22557
22579
  const evaluationTrace = [];
22558
22580
  // Evaluate rules in order (first match wins)
@@ -22599,8 +22621,8 @@ class BasicAuthorizationPolicy {
22599
22621
  }
22600
22622
  }
22601
22623
  // Check action match
22602
- if (!rule.actions.has('*') && !rule.actions.has(resolvedAction)) {
22603
- step.expression = `action: ${resolvedAction} not in [${Array.from(rule.actions).join(', ')}]`;
22624
+ if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
22625
+ step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
22604
22626
  step.result = false;
22605
22627
  evaluationTrace.push(step);
22606
22628
  continue;
@@ -22667,6 +22689,9 @@ class BasicAuthorizationPolicy {
22667
22689
  };
22668
22690
  }
22669
22691
  validateDefaultEffect(effect) {
22692
+ if (effect === undefined || effect === null) {
22693
+ return 'deny';
22694
+ }
22670
22695
  if (effect !== 'allow' && effect !== 'deny') {
22671
22696
  throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
22672
22697
  }
@@ -22739,10 +22764,11 @@ class BasicAuthorizationPolicy {
22739
22764
  }
22740
22765
  // Handle single action
22741
22766
  if (typeof action === 'string') {
22742
- if (!VALID_ACTIONS.includes(action)) {
22767
+ const normalized = this.normalizeActionToken(action);
22768
+ if (!normalized) {
22743
22769
  throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22744
22770
  }
22745
- return new Set([action]);
22771
+ return new Set([normalized]);
22746
22772
  }
22747
22773
  // Handle array of actions
22748
22774
  if (!Array.isArray(action)) {
@@ -22756,10 +22782,11 @@ class BasicAuthorizationPolicy {
22756
22782
  if (typeof a !== 'string') {
22757
22783
  throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
22758
22784
  }
22759
- if (!VALID_ACTIONS.includes(a)) {
22785
+ const normalized = this.normalizeActionToken(a);
22786
+ if (!normalized) {
22760
22787
  throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22761
22788
  }
22762
- actions.add(a);
22789
+ actions.add(normalized);
22763
22790
  }
22764
22791
  return actions;
22765
22792
  }
@@ -22862,11 +22889,12 @@ class BasicAuthorizationPolicy {
22862
22889
  }
22863
22890
  // Handle single origin type
22864
22891
  if (typeof originType === 'string') {
22865
- const normalized = originType.trim().toLowerCase();
22866
- if (!normalized) {
22892
+ const trimmed = originType.trim();
22893
+ if (!trimmed) {
22867
22894
  throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
22868
22895
  }
22869
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22896
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22897
+ if (!normalized) {
22870
22898
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22871
22899
  }
22872
22900
  return new Set([normalized]);
@@ -22883,17 +22911,50 @@ class BasicAuthorizationPolicy {
22883
22911
  if (typeof ot !== 'string') {
22884
22912
  throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
22885
22913
  }
22886
- const normalized = ot.trim().toLowerCase();
22887
- if (!normalized) {
22914
+ const trimmed = ot.trim();
22915
+ if (!trimmed) {
22888
22916
  throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
22889
22917
  }
22890
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22918
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22919
+ if (!normalized) {
22891
22920
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22892
22921
  }
22893
22922
  originTypes.add(normalized);
22894
22923
  }
22895
22924
  return originTypes;
22896
22925
  }
22926
+ normalizeActionToken(value) {
22927
+ const trimmed = value.trim();
22928
+ if (!trimmed) {
22929
+ return null;
22930
+ }
22931
+ if (trimmed === '*') {
22932
+ return '*';
22933
+ }
22934
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
22935
+ const map = {
22936
+ connect: 'Connect',
22937
+ forwardupstream: 'ForwardUpstream',
22938
+ forwarddownstream: 'ForwardDownstream',
22939
+ forwardpeer: 'ForwardPeer',
22940
+ deliverlocal: 'DeliverLocal',
22941
+ };
22942
+ return map[normalized] ?? null;
22943
+ }
22944
+ normalizeOriginTypeToken(value) {
22945
+ const trimmed = value.trim();
22946
+ if (!trimmed) {
22947
+ return null;
22948
+ }
22949
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
22950
+ const map = {
22951
+ downstream: 'downstream',
22952
+ upstream: 'upstream',
22953
+ peer: 'peer',
22954
+ local: 'local',
22955
+ };
22956
+ return map[normalized] ?? null;
22957
+ }
22897
22958
  }
22898
22959
 
22899
22960
  var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
@@ -42557,16 +42618,22 @@ class LocalFileAuthorizationPolicySource {
42557
42618
  const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
42558
42619
  // Ensure we have a type field for the factory
42559
42620
  if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
42560
- throw new Error(`Policy definition at ${this.path} must have a 'type' field, ` +
42561
- `or policyFactory config must be provided`);
42621
+ logger$1.warning('policy_type_missing_defaulting_to_basic', {
42622
+ path: this.path,
42623
+ });
42624
+ factoryConfig.type =
42625
+ 'BasicAuthorizationPolicy';
42562
42626
  }
42563
42627
  // Build the factory config with the policy definition
42564
42628
  // The file content IS the policy definition, so we extract the type
42565
42629
  // and wrap the remaining content as the policyDefinition
42566
- const { type, ...restOfFile } = policyDefinition;
42630
+ const { type: fileType, ...restOfFile } = policyDefinition;
42631
+ const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
42632
+ ? fileType
42633
+ : factoryConfig.type;
42567
42634
  const mergedConfig = this.policyFactoryConfig != null
42568
42635
  ? { ...this.policyFactoryConfig, policyDefinition }
42569
- : { type: factoryConfig.type, policyDefinition: restOfFile };
42636
+ : { type: resolvedType, policyDefinition: restOfFile };
42570
42637
  // Create the policy using the factory system
42571
42638
  const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
42572
42639
  if (!policy) {
@@ -13,12 +13,12 @@ import fastify from 'fastify';
13
13
  import websocketPlugin from '@fastify/websocket';
14
14
 
15
15
  // This file is auto-generated during build - do not edit manually
16
- // Generated from package.json version: 0.4.2
16
+ // Generated from package.json version: 0.4.4
17
17
  /**
18
18
  * The package version, injected at build time.
19
19
  * @internal
20
20
  */
21
- const VERSION = '0.4.2';
21
+ const VERSION = '0.4.4';
22
22
 
23
23
  /**
24
24
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -21812,6 +21812,7 @@ const PROFILE_NAME_DEFAULT = 'jwt';
21812
21812
  const PROFILE_NAME_OAUTH2 = 'oauth2';
21813
21813
  const PROFILE_NAME_OAUTH2_GATED = 'oauth2-gated';
21814
21814
  const PROFILE_NAME_OAUTH2_CALLBACK = 'oauth2-callback';
21815
+ const PROFILE_NAME_POLICY_LOCALFILE = 'policy-localfile';
21815
21816
  const PROFILE_NAME_NOOP$2 = 'noop';
21816
21817
  const ENV_VAR_JWT_TRUSTED_ISSUER$1 = 'FAME_JWT_TRUSTED_ISSUER';
21817
21818
  const ENV_VAR_JWT_ALGORITHM$1 = 'FAME_JWT_ALGORITHM';
@@ -21819,18 +21820,21 @@ const ENV_VAR_JWT_AUDIENCE$2 = 'FAME_JWT_AUDIENCE';
21819
21820
  const ENV_VAR_JWKS_URL$1 = 'FAME_JWKS_URL';
21820
21821
  const ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY$1 = 'FAME_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY';
21821
21822
  const ENV_VAR_TRUSTED_CLIENT_SCOPE$1 = 'FAME_TRUSTED_CLIENT_SCOPE';
21823
+ const ENV_VAR_AUTH_POLICY_PATH = 'FAME_AUTH_POLICY_PATH';
21824
+ const ENV_VAR_AUTH_POLICY_FORMAT = 'FAME_AUTH_POLICY_FORMAT';
21822
21825
  const ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER$1 = 'FAME_JWT_REVERSE_AUTH_TRUSTED_ISSUER';
21823
21826
  const ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE$1 = 'FAME_JWT_REVERSE_AUTH_AUDIENCE';
21824
21827
  const ENV_VAR_HMAC_SECRET$1 = 'FAME_HMAC_SECRET';
21825
21828
  const DEFAULT_REVERSE_AUTH_ISSUER = 'reverse-auth.naylence.ai';
21826
21829
  const DEFAULT_REVERSE_AUTH_AUDIENCE = 'dev.naylence.ai';
21830
+ const DEFAULT_VERIFIER_CONFIG = {
21831
+ type: 'JWKSJWTTokenVerifier',
21832
+ jwks_url: Expressions.env(ENV_VAR_JWKS_URL$1),
21833
+ issuer: Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER$1),
21834
+ };
21827
21835
  const DEFAULT_PROFILE = {
21828
21836
  type: 'DefaultAuthorizer',
21829
- verifier: {
21830
- type: 'JWKSJWTTokenVerifier',
21831
- jwks_url: Expressions.env(ENV_VAR_JWKS_URL$1),
21832
- issuer: Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER$1),
21833
- },
21837
+ verifier: DEFAULT_VERIFIER_CONFIG,
21834
21838
  };
21835
21839
  const OAUTH2_PROFILE = {
21836
21840
  type: 'OAuth2Authorizer',
@@ -21875,11 +21879,22 @@ const OAUTH2_CALLBACK_PROFILE = {
21875
21879
  const NOOP_PROFILE$2 = {
21876
21880
  type: 'NoopAuthorizer',
21877
21881
  };
21882
+ const DEFAULT_POLICY_SOURCE = {
21883
+ type: 'LocalFileAuthorizationPolicySource',
21884
+ path: Expressions.env(ENV_VAR_AUTH_POLICY_PATH, './auth-policy.yaml'),
21885
+ format: Expressions.env(ENV_VAR_AUTH_POLICY_FORMAT, 'auto'),
21886
+ };
21887
+ const POLICY_LOCALFILE_PROFILE = {
21888
+ type: 'PolicyAuthorizer',
21889
+ verifier: DEFAULT_VERIFIER_CONFIG,
21890
+ policySource: DEFAULT_POLICY_SOURCE,
21891
+ };
21878
21892
  const PROFILE_MAP$5 = {
21879
21893
  [PROFILE_NAME_DEFAULT]: DEFAULT_PROFILE,
21880
21894
  [PROFILE_NAME_OAUTH2]: OAUTH2_PROFILE,
21881
21895
  [PROFILE_NAME_OAUTH2_GATED]: OAUTH2_GATED_PROFILE,
21882
21896
  [PROFILE_NAME_OAUTH2_CALLBACK]: OAUTH2_CALLBACK_PROFILE,
21897
+ [PROFILE_NAME_POLICY_LOCALFILE]: POLICY_LOCALFILE_PROFILE,
21883
21898
  [PROFILE_NAME_NOOP$2]: NOOP_PROFILE$2,
21884
21899
  };
21885
21900
  const PROFILE_ALIASES$1 = {
@@ -21893,6 +21908,9 @@ const PROFILE_ALIASES$1 = {
21893
21908
  'oauth2-callback': PROFILE_NAME_OAUTH2_CALLBACK,
21894
21909
  oauth2_callback: PROFILE_NAME_OAUTH2_CALLBACK,
21895
21910
  'reverse-auth': PROFILE_NAME_OAUTH2_CALLBACK,
21911
+ policy: PROFILE_NAME_POLICY_LOCALFILE,
21912
+ 'policy-localfile': PROFILE_NAME_POLICY_LOCALFILE,
21913
+ policy_localfile: PROFILE_NAME_POLICY_LOCALFILE,
21896
21914
  noop: PROFILE_NAME_NOOP$2,
21897
21915
  'no-op': PROFILE_NAME_NOOP$2,
21898
21916
  no_op: PROFILE_NAME_NOOP$2,
@@ -21968,6 +21986,8 @@ function deepClone$4(value) {
21968
21986
  var authorizationProfileFactory = /*#__PURE__*/Object.freeze({
21969
21987
  __proto__: null,
21970
21988
  AuthorizationProfileFactory: AuthorizationProfileFactory,
21989
+ ENV_VAR_AUTH_POLICY_FORMAT: ENV_VAR_AUTH_POLICY_FORMAT,
21990
+ ENV_VAR_AUTH_POLICY_PATH: ENV_VAR_AUTH_POLICY_PATH,
21971
21991
  ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY: ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY$1,
21972
21992
  ENV_VAR_HMAC_SECRET: ENV_VAR_HMAC_SECRET$1,
21973
21993
  ENV_VAR_JWKS_URL: ENV_VAR_JWKS_URL$1,
@@ -21983,6 +22003,7 @@ var authorizationProfileFactory = /*#__PURE__*/Object.freeze({
21983
22003
  PROFILE_NAME_OAUTH2: PROFILE_NAME_OAUTH2,
21984
22004
  PROFILE_NAME_OAUTH2_CALLBACK: PROFILE_NAME_OAUTH2_CALLBACK,
21985
22005
  PROFILE_NAME_OAUTH2_GATED: PROFILE_NAME_OAUTH2_GATED,
22006
+ PROFILE_NAME_POLICY_LOCALFILE: PROFILE_NAME_POLICY_LOCALFILE,
21986
22007
  default: AuthorizationProfileFactory
21987
22008
  });
21988
22009
 
@@ -22541,6 +22562,7 @@ class BasicAuthorizationPolicy {
22541
22562
  // Action must be explicitly provided; default to wildcard if omitted
22542
22563
  // for backward compatibility during transition
22543
22564
  const resolvedAction = action ?? '*';
22565
+ const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
22544
22566
  const address = extractAddress(envelope);
22545
22567
  const grantedScopes = extractGrantedScopes(context);
22546
22568
  const rawFrameType = envelope.frame
@@ -22550,8 +22572,8 @@ class BasicAuthorizationPolicy {
22550
22572
  : '';
22551
22573
  // Extract and normalize origin type for rule matching
22552
22574
  const rawOriginType = context?.originType;
22553
- const originTypeNormalized = typeof rawOriginType === 'string' && rawOriginType.trim().length > 0
22554
- ? rawOriginType.trim().toLowerCase()
22575
+ const originTypeNormalized = typeof rawOriginType === 'string'
22576
+ ? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
22555
22577
  : undefined;
22556
22578
  const evaluationTrace = [];
22557
22579
  // Evaluate rules in order (first match wins)
@@ -22598,8 +22620,8 @@ class BasicAuthorizationPolicy {
22598
22620
  }
22599
22621
  }
22600
22622
  // Check action match
22601
- if (!rule.actions.has('*') && !rule.actions.has(resolvedAction)) {
22602
- step.expression = `action: ${resolvedAction} not in [${Array.from(rule.actions).join(', ')}]`;
22623
+ if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
22624
+ step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
22603
22625
  step.result = false;
22604
22626
  evaluationTrace.push(step);
22605
22627
  continue;
@@ -22666,6 +22688,9 @@ class BasicAuthorizationPolicy {
22666
22688
  };
22667
22689
  }
22668
22690
  validateDefaultEffect(effect) {
22691
+ if (effect === undefined || effect === null) {
22692
+ return 'deny';
22693
+ }
22669
22694
  if (effect !== 'allow' && effect !== 'deny') {
22670
22695
  throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
22671
22696
  }
@@ -22738,10 +22763,11 @@ class BasicAuthorizationPolicy {
22738
22763
  }
22739
22764
  // Handle single action
22740
22765
  if (typeof action === 'string') {
22741
- if (!VALID_ACTIONS.includes(action)) {
22766
+ const normalized = this.normalizeActionToken(action);
22767
+ if (!normalized) {
22742
22768
  throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22743
22769
  }
22744
- return new Set([action]);
22770
+ return new Set([normalized]);
22745
22771
  }
22746
22772
  // Handle array of actions
22747
22773
  if (!Array.isArray(action)) {
@@ -22755,10 +22781,11 @@ class BasicAuthorizationPolicy {
22755
22781
  if (typeof a !== 'string') {
22756
22782
  throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
22757
22783
  }
22758
- if (!VALID_ACTIONS.includes(a)) {
22784
+ const normalized = this.normalizeActionToken(a);
22785
+ if (!normalized) {
22759
22786
  throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22760
22787
  }
22761
- actions.add(a);
22788
+ actions.add(normalized);
22762
22789
  }
22763
22790
  return actions;
22764
22791
  }
@@ -22861,11 +22888,12 @@ class BasicAuthorizationPolicy {
22861
22888
  }
22862
22889
  // Handle single origin type
22863
22890
  if (typeof originType === 'string') {
22864
- const normalized = originType.trim().toLowerCase();
22865
- if (!normalized) {
22891
+ const trimmed = originType.trim();
22892
+ if (!trimmed) {
22866
22893
  throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
22867
22894
  }
22868
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22895
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22896
+ if (!normalized) {
22869
22897
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22870
22898
  }
22871
22899
  return new Set([normalized]);
@@ -22882,17 +22910,50 @@ class BasicAuthorizationPolicy {
22882
22910
  if (typeof ot !== 'string') {
22883
22911
  throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
22884
22912
  }
22885
- const normalized = ot.trim().toLowerCase();
22886
- if (!normalized) {
22913
+ const trimmed = ot.trim();
22914
+ if (!trimmed) {
22887
22915
  throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
22888
22916
  }
22889
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22917
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22918
+ if (!normalized) {
22890
22919
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22891
22920
  }
22892
22921
  originTypes.add(normalized);
22893
22922
  }
22894
22923
  return originTypes;
22895
22924
  }
22925
+ normalizeActionToken(value) {
22926
+ const trimmed = value.trim();
22927
+ if (!trimmed) {
22928
+ return null;
22929
+ }
22930
+ if (trimmed === '*') {
22931
+ return '*';
22932
+ }
22933
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
22934
+ const map = {
22935
+ connect: 'Connect',
22936
+ forwardupstream: 'ForwardUpstream',
22937
+ forwarddownstream: 'ForwardDownstream',
22938
+ forwardpeer: 'ForwardPeer',
22939
+ deliverlocal: 'DeliverLocal',
22940
+ };
22941
+ return map[normalized] ?? null;
22942
+ }
22943
+ normalizeOriginTypeToken(value) {
22944
+ const trimmed = value.trim();
22945
+ if (!trimmed) {
22946
+ return null;
22947
+ }
22948
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
22949
+ const map = {
22950
+ downstream: 'downstream',
22951
+ upstream: 'upstream',
22952
+ peer: 'peer',
22953
+ local: 'local',
22954
+ };
22955
+ return map[normalized] ?? null;
22956
+ }
22896
22957
  }
22897
22958
 
22898
22959
  var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
@@ -42556,16 +42617,22 @@ class LocalFileAuthorizationPolicySource {
42556
42617
  const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
42557
42618
  // Ensure we have a type field for the factory
42558
42619
  if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
42559
- throw new Error(`Policy definition at ${this.path} must have a 'type' field, ` +
42560
- `or policyFactory config must be provided`);
42620
+ logger$1.warning('policy_type_missing_defaulting_to_basic', {
42621
+ path: this.path,
42622
+ });
42623
+ factoryConfig.type =
42624
+ 'BasicAuthorizationPolicy';
42561
42625
  }
42562
42626
  // Build the factory config with the policy definition
42563
42627
  // The file content IS the policy definition, so we extract the type
42564
42628
  // and wrap the remaining content as the policyDefinition
42565
- const { type, ...restOfFile } = policyDefinition;
42629
+ const { type: fileType, ...restOfFile } = policyDefinition;
42630
+ const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
42631
+ ? fileType
42632
+ : factoryConfig.type;
42566
42633
  const mergedConfig = this.policyFactoryConfig != null
42567
42634
  ? { ...this.policyFactoryConfig, policyDefinition }
42568
- : { type: factoryConfig.type, policyDefinition: restOfFile };
42635
+ : { type: resolvedType, policyDefinition: restOfFile };
42569
42636
  // Create the policy using the factory system
42570
42637
  const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
42571
42638
  if (!policy) {