@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.
- package/dist/browser/index.cjs +66 -20
- package/dist/browser/index.mjs +66 -20
- package/dist/cjs/naylence/fame/security/auth/policy/basic-authorization-policy.js +54 -14
- package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +10 -4
- package/dist/cjs/version.js +2 -2
- package/dist/esm/naylence/fame/security/auth/policy/basic-authorization-policy.js +54 -14
- package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +10 -4
- package/dist/esm/version.js +2 -2
- package/dist/node/index.cjs +66 -20
- package/dist/node/index.mjs +66 -20
- package/dist/node/node.cjs +66 -20
- package/dist/node/node.mjs +66 -20
- package/dist/types/naylence/fame/security/auth/policy/authorization-policy-definition.d.ts +8 -2
- package/dist/types/naylence/fame/security/auth/policy/basic-authorization-policy.d.ts +2 -0
- package/dist/types/version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -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'
|
|
103
|
-
?
|
|
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(
|
|
151
|
-
step.expression = `action: ${
|
|
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
|
-
|
|
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([
|
|
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
|
-
|
|
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(
|
|
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
|
|
414
|
-
if (!
|
|
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
|
-
|
|
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
|
|
435
|
-
if (!
|
|
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
|
-
|
|
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
|
}
|
package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js
CHANGED
|
@@ -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
|
-
|
|
91
|
-
|
|
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:
|
|
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) {
|
package/dist/esm/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file is auto-generated during build - do not edit manually
|
|
2
|
-
// Generated from package.json version: 0.4.
|
|
2
|
+
// Generated from package.json version: 0.4.4
|
|
3
3
|
/**
|
|
4
4
|
* The package version, injected at build time.
|
|
5
5
|
* @internal
|
|
6
6
|
*/
|
|
7
|
-
export const VERSION = '0.4.
|
|
7
|
+
export const VERSION = '0.4.4';
|
package/dist/node/index.cjs
CHANGED
|
@@ -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.
|
|
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.
|
|
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'
|
|
22576
|
-
?
|
|
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(
|
|
22624
|
-
step.expression = `action: ${
|
|
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
|
-
|
|
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([
|
|
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
|
-
|
|
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(
|
|
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
|
|
22887
|
-
if (!
|
|
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
|
-
|
|
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
|
|
22908
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
42582
|
-
|
|
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:
|
|
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) {
|
package/dist/node/index.mjs
CHANGED
|
@@ -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.
|
|
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.
|
|
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'
|
|
22575
|
-
?
|
|
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(
|
|
22623
|
-
step.expression = `action: ${
|
|
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
|
-
|
|
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([
|
|
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
|
-
|
|
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(
|
|
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
|
|
22886
|
-
if (!
|
|
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
|
-
|
|
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
|
|
22907
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
42581
|
-
|
|
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:
|
|
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) {
|