@naylence/runtime 0.4.3 → 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.
@@ -90,6 +90,7 @@ export class BasicAuthorizationPolicy {
90
90
  // Action must be explicitly provided; default to wildcard if omitted
91
91
  // for backward compatibility during transition
92
92
  const resolvedAction = action ?? '*';
93
+ const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
93
94
  const address = extractAddress(envelope);
94
95
  const grantedScopes = extractGrantedScopes(context);
95
96
  const rawFrameType = envelope.frame
@@ -99,8 +100,8 @@ export class BasicAuthorizationPolicy {
99
100
  : '';
100
101
  // Extract and normalize origin type for rule matching
101
102
  const rawOriginType = context?.originType;
102
- const originTypeNormalized = typeof rawOriginType === 'string' && rawOriginType.trim().length > 0
103
- ? rawOriginType.trim().toLowerCase()
103
+ const originTypeNormalized = typeof rawOriginType === 'string'
104
+ ? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
104
105
  : undefined;
105
106
  const evaluationTrace = [];
106
107
  // Evaluate rules in order (first match wins)
@@ -147,8 +148,8 @@ export class BasicAuthorizationPolicy {
147
148
  }
148
149
  }
149
150
  // Check action match
150
- if (!rule.actions.has('*') && !rule.actions.has(resolvedAction)) {
151
- step.expression = `action: ${resolvedAction} not in [${Array.from(rule.actions).join(', ')}]`;
151
+ if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
152
+ step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
152
153
  step.result = false;
153
154
  evaluationTrace.push(step);
154
155
  continue;
@@ -215,6 +216,9 @@ export class BasicAuthorizationPolicy {
215
216
  };
216
217
  }
217
218
  validateDefaultEffect(effect) {
219
+ if (effect === undefined || effect === null) {
220
+ return 'deny';
221
+ }
218
222
  if (effect !== 'allow' && effect !== 'deny') {
219
223
  throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
220
224
  }
@@ -287,10 +291,11 @@ export class BasicAuthorizationPolicy {
287
291
  }
288
292
  // Handle single action
289
293
  if (typeof action === 'string') {
290
- if (!VALID_ACTIONS.includes(action)) {
294
+ const normalized = this.normalizeActionToken(action);
295
+ if (!normalized) {
291
296
  throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
292
297
  }
293
- return new Set([action]);
298
+ return new Set([normalized]);
294
299
  }
295
300
  // Handle array of actions
296
301
  if (!Array.isArray(action)) {
@@ -304,10 +309,11 @@ export class BasicAuthorizationPolicy {
304
309
  if (typeof a !== 'string') {
305
310
  throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
306
311
  }
307
- if (!VALID_ACTIONS.includes(a)) {
312
+ const normalized = this.normalizeActionToken(a);
313
+ if (!normalized) {
308
314
  throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
309
315
  }
310
- actions.add(a);
316
+ actions.add(normalized);
311
317
  }
312
318
  return actions;
313
319
  }
@@ -410,11 +416,12 @@ export class BasicAuthorizationPolicy {
410
416
  }
411
417
  // Handle single origin type
412
418
  if (typeof originType === 'string') {
413
- const normalized = originType.trim().toLowerCase();
414
- if (!normalized) {
419
+ const trimmed = originType.trim();
420
+ if (!trimmed) {
415
421
  throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
416
422
  }
417
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
423
+ const normalized = this.normalizeOriginTypeToken(trimmed);
424
+ if (!normalized) {
418
425
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
419
426
  }
420
427
  return new Set([normalized]);
@@ -431,15 +438,48 @@ export class BasicAuthorizationPolicy {
431
438
  if (typeof ot !== 'string') {
432
439
  throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
433
440
  }
434
- const normalized = ot.trim().toLowerCase();
435
- if (!normalized) {
441
+ const trimmed = ot.trim();
442
+ if (!trimmed) {
436
443
  throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
437
444
  }
438
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
445
+ const normalized = this.normalizeOriginTypeToken(trimmed);
446
+ if (!normalized) {
439
447
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
440
448
  }
441
449
  originTypes.add(normalized);
442
450
  }
443
451
  return originTypes;
444
452
  }
453
+ normalizeActionToken(value) {
454
+ const trimmed = value.trim();
455
+ if (!trimmed) {
456
+ return null;
457
+ }
458
+ if (trimmed === '*') {
459
+ return '*';
460
+ }
461
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
462
+ const map = {
463
+ connect: 'Connect',
464
+ forwardupstream: 'ForwardUpstream',
465
+ forwarddownstream: 'ForwardDownstream',
466
+ forwardpeer: 'ForwardPeer',
467
+ deliverlocal: 'DeliverLocal',
468
+ };
469
+ return map[normalized] ?? null;
470
+ }
471
+ normalizeOriginTypeToken(value) {
472
+ const trimmed = value.trim();
473
+ if (!trimmed) {
474
+ return null;
475
+ }
476
+ const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
477
+ const map = {
478
+ downstream: 'downstream',
479
+ upstream: 'upstream',
480
+ peer: 'peer',
481
+ local: 'local',
482
+ };
483
+ return map[normalized] ?? null;
484
+ }
445
485
  }
@@ -87,16 +87,22 @@ export class LocalFileAuthorizationPolicySource {
87
87
  const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
88
88
  // Ensure we have a type field for the factory
89
89
  if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
90
- throw new Error(`Policy definition at ${this.path} must have a 'type' field, ` +
91
- `or policyFactory config must be provided`);
90
+ logger.warning('policy_type_missing_defaulting_to_basic', {
91
+ path: this.path,
92
+ });
93
+ factoryConfig.type =
94
+ 'BasicAuthorizationPolicy';
92
95
  }
93
96
  // Build the factory config with the policy definition
94
97
  // The file content IS the policy definition, so we extract the type
95
98
  // and wrap the remaining content as the policyDefinition
96
- const { type, ...restOfFile } = policyDefinition;
99
+ const { type: fileType, ...restOfFile } = policyDefinition;
100
+ const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
101
+ ? fileType
102
+ : factoryConfig.type;
97
103
  const mergedConfig = this.policyFactoryConfig != null
98
104
  ? { ...this.policyFactoryConfig, policyDefinition }
99
- : { type: factoryConfig.type, policyDefinition: restOfFile };
105
+ : { type: resolvedType, policyDefinition: restOfFile };
100
106
  // Create the policy using the factory system
101
107
  const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
102
108
  if (!policy) {
@@ -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.3
2
+ // Generated from package.json version: 0.4.4
3
3
  /**
4
4
  * The package version, injected at build time.
5
5
  * @internal
6
6
  */
7
- export const VERSION = '0.4.3';
7
+ export const VERSION = '0.4.4';
@@ -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.3
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.3';
22
+ const VERSION = '0.4.4';
23
23
 
24
24
  /**
25
25
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -22563,6 +22563,7 @@ class BasicAuthorizationPolicy {
22563
22563
  // Action must be explicitly provided; default to wildcard if omitted
22564
22564
  // for backward compatibility during transition
22565
22565
  const resolvedAction = action ?? '*';
22566
+ const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
22566
22567
  const address = extractAddress(envelope);
22567
22568
  const grantedScopes = extractGrantedScopes(context);
22568
22569
  const rawFrameType = envelope.frame
@@ -22572,8 +22573,8 @@ class BasicAuthorizationPolicy {
22572
22573
  : '';
22573
22574
  // Extract and normalize origin type for rule matching
22574
22575
  const rawOriginType = context?.originType;
22575
- const originTypeNormalized = typeof rawOriginType === 'string' && rawOriginType.trim().length > 0
22576
- ? rawOriginType.trim().toLowerCase()
22576
+ const originTypeNormalized = typeof rawOriginType === 'string'
22577
+ ? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
22577
22578
  : undefined;
22578
22579
  const evaluationTrace = [];
22579
22580
  // Evaluate rules in order (first match wins)
@@ -22620,8 +22621,8 @@ class BasicAuthorizationPolicy {
22620
22621
  }
22621
22622
  }
22622
22623
  // Check action match
22623
- if (!rule.actions.has('*') && !rule.actions.has(resolvedAction)) {
22624
- 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(', ')}]`;
22625
22626
  step.result = false;
22626
22627
  evaluationTrace.push(step);
22627
22628
  continue;
@@ -22688,6 +22689,9 @@ class BasicAuthorizationPolicy {
22688
22689
  };
22689
22690
  }
22690
22691
  validateDefaultEffect(effect) {
22692
+ if (effect === undefined || effect === null) {
22693
+ return 'deny';
22694
+ }
22691
22695
  if (effect !== 'allow' && effect !== 'deny') {
22692
22696
  throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
22693
22697
  }
@@ -22760,10 +22764,11 @@ class BasicAuthorizationPolicy {
22760
22764
  }
22761
22765
  // Handle single action
22762
22766
  if (typeof action === 'string') {
22763
- if (!VALID_ACTIONS.includes(action)) {
22767
+ const normalized = this.normalizeActionToken(action);
22768
+ if (!normalized) {
22764
22769
  throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22765
22770
  }
22766
- return new Set([action]);
22771
+ return new Set([normalized]);
22767
22772
  }
22768
22773
  // Handle array of actions
22769
22774
  if (!Array.isArray(action)) {
@@ -22777,10 +22782,11 @@ class BasicAuthorizationPolicy {
22777
22782
  if (typeof a !== 'string') {
22778
22783
  throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
22779
22784
  }
22780
- if (!VALID_ACTIONS.includes(a)) {
22785
+ const normalized = this.normalizeActionToken(a);
22786
+ if (!normalized) {
22781
22787
  throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22782
22788
  }
22783
- actions.add(a);
22789
+ actions.add(normalized);
22784
22790
  }
22785
22791
  return actions;
22786
22792
  }
@@ -22883,11 +22889,12 @@ class BasicAuthorizationPolicy {
22883
22889
  }
22884
22890
  // Handle single origin type
22885
22891
  if (typeof originType === 'string') {
22886
- const normalized = originType.trim().toLowerCase();
22887
- if (!normalized) {
22892
+ const trimmed = originType.trim();
22893
+ if (!trimmed) {
22888
22894
  throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
22889
22895
  }
22890
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22896
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22897
+ if (!normalized) {
22891
22898
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22892
22899
  }
22893
22900
  return new Set([normalized]);
@@ -22904,17 +22911,50 @@ class BasicAuthorizationPolicy {
22904
22911
  if (typeof ot !== 'string') {
22905
22912
  throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
22906
22913
  }
22907
- const normalized = ot.trim().toLowerCase();
22908
- if (!normalized) {
22914
+ const trimmed = ot.trim();
22915
+ if (!trimmed) {
22909
22916
  throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
22910
22917
  }
22911
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22918
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22919
+ if (!normalized) {
22912
22920
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22913
22921
  }
22914
22922
  originTypes.add(normalized);
22915
22923
  }
22916
22924
  return originTypes;
22917
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
+ }
22918
22958
  }
22919
22959
 
22920
22960
  var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
@@ -42578,16 +42618,22 @@ class LocalFileAuthorizationPolicySource {
42578
42618
  const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
42579
42619
  // Ensure we have a type field for the factory
42580
42620
  if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
42581
- throw new Error(`Policy definition at ${this.path} must have a 'type' field, ` +
42582
- `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';
42583
42626
  }
42584
42627
  // Build the factory config with the policy definition
42585
42628
  // The file content IS the policy definition, so we extract the type
42586
42629
  // and wrap the remaining content as the policyDefinition
42587
- 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;
42588
42634
  const mergedConfig = this.policyFactoryConfig != null
42589
42635
  ? { ...this.policyFactoryConfig, policyDefinition }
42590
- : { type: factoryConfig.type, policyDefinition: restOfFile };
42636
+ : { type: resolvedType, policyDefinition: restOfFile };
42591
42637
  // Create the policy using the factory system
42592
42638
  const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
42593
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.3
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.3';
21
+ const VERSION = '0.4.4';
22
22
 
23
23
  /**
24
24
  * Fame protocol specific error classes with WebSocket close codes and proper inheritance.
@@ -22562,6 +22562,7 @@ class BasicAuthorizationPolicy {
22562
22562
  // Action must be explicitly provided; default to wildcard if omitted
22563
22563
  // for backward compatibility during transition
22564
22564
  const resolvedAction = action ?? '*';
22565
+ const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
22565
22566
  const address = extractAddress(envelope);
22566
22567
  const grantedScopes = extractGrantedScopes(context);
22567
22568
  const rawFrameType = envelope.frame
@@ -22571,8 +22572,8 @@ class BasicAuthorizationPolicy {
22571
22572
  : '';
22572
22573
  // Extract and normalize origin type for rule matching
22573
22574
  const rawOriginType = context?.originType;
22574
- const originTypeNormalized = typeof rawOriginType === 'string' && rawOriginType.trim().length > 0
22575
- ? rawOriginType.trim().toLowerCase()
22575
+ const originTypeNormalized = typeof rawOriginType === 'string'
22576
+ ? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
22576
22577
  : undefined;
22577
22578
  const evaluationTrace = [];
22578
22579
  // Evaluate rules in order (first match wins)
@@ -22619,8 +22620,8 @@ class BasicAuthorizationPolicy {
22619
22620
  }
22620
22621
  }
22621
22622
  // Check action match
22622
- if (!rule.actions.has('*') && !rule.actions.has(resolvedAction)) {
22623
- 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(', ')}]`;
22624
22625
  step.result = false;
22625
22626
  evaluationTrace.push(step);
22626
22627
  continue;
@@ -22687,6 +22688,9 @@ class BasicAuthorizationPolicy {
22687
22688
  };
22688
22689
  }
22689
22690
  validateDefaultEffect(effect) {
22691
+ if (effect === undefined || effect === null) {
22692
+ return 'deny';
22693
+ }
22690
22694
  if (effect !== 'allow' && effect !== 'deny') {
22691
22695
  throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
22692
22696
  }
@@ -22759,10 +22763,11 @@ class BasicAuthorizationPolicy {
22759
22763
  }
22760
22764
  // Handle single action
22761
22765
  if (typeof action === 'string') {
22762
- if (!VALID_ACTIONS.includes(action)) {
22766
+ const normalized = this.normalizeActionToken(action);
22767
+ if (!normalized) {
22763
22768
  throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22764
22769
  }
22765
- return new Set([action]);
22770
+ return new Set([normalized]);
22766
22771
  }
22767
22772
  // Handle array of actions
22768
22773
  if (!Array.isArray(action)) {
@@ -22776,10 +22781,11 @@ class BasicAuthorizationPolicy {
22776
22781
  if (typeof a !== 'string') {
22777
22782
  throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
22778
22783
  }
22779
- if (!VALID_ACTIONS.includes(a)) {
22784
+ const normalized = this.normalizeActionToken(a);
22785
+ if (!normalized) {
22780
22786
  throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
22781
22787
  }
22782
- actions.add(a);
22788
+ actions.add(normalized);
22783
22789
  }
22784
22790
  return actions;
22785
22791
  }
@@ -22882,11 +22888,12 @@ class BasicAuthorizationPolicy {
22882
22888
  }
22883
22889
  // Handle single origin type
22884
22890
  if (typeof originType === 'string') {
22885
- const normalized = originType.trim().toLowerCase();
22886
- if (!normalized) {
22891
+ const trimmed = originType.trim();
22892
+ if (!trimmed) {
22887
22893
  throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
22888
22894
  }
22889
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22895
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22896
+ if (!normalized) {
22890
22897
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22891
22898
  }
22892
22899
  return new Set([normalized]);
@@ -22903,17 +22910,50 @@ class BasicAuthorizationPolicy {
22903
22910
  if (typeof ot !== 'string') {
22904
22911
  throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
22905
22912
  }
22906
- const normalized = ot.trim().toLowerCase();
22907
- if (!normalized) {
22913
+ const trimmed = ot.trim();
22914
+ if (!trimmed) {
22908
22915
  throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
22909
22916
  }
22910
- if (!VALID_ORIGIN_TYPES.includes(normalized)) {
22917
+ const normalized = this.normalizeOriginTypeToken(trimmed);
22918
+ if (!normalized) {
22911
22919
  throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
22912
22920
  }
22913
22921
  originTypes.add(normalized);
22914
22922
  }
22915
22923
  return originTypes;
22916
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
+ }
22917
22957
  }
22918
22958
 
22919
22959
  var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
@@ -42577,16 +42617,22 @@ class LocalFileAuthorizationPolicySource {
42577
42617
  const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
42578
42618
  // Ensure we have a type field for the factory
42579
42619
  if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
42580
- throw new Error(`Policy definition at ${this.path} must have a 'type' field, ` +
42581
- `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';
42582
42625
  }
42583
42626
  // Build the factory config with the policy definition
42584
42627
  // The file content IS the policy definition, so we extract the type
42585
42628
  // and wrap the remaining content as the policyDefinition
42586
- 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;
42587
42633
  const mergedConfig = this.policyFactoryConfig != null
42588
42634
  ? { ...this.policyFactoryConfig, policyDefinition }
42589
- : { type: factoryConfig.type, policyDefinition: restOfFile };
42635
+ : { type: resolvedType, policyDefinition: restOfFile };
42590
42636
  // Create the policy using the factory system
42591
42637
  const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
42592
42638
  if (!policy) {