@naylence/runtime 0.4.3 → 0.4.5
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 +76 -22
- package/dist/browser/index.mjs +77 -23
- package/dist/cjs/naylence/fame/security/auth/authorization-profile-factory.js +10 -2
- 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/authorization-profile-factory.js +11 -3
- 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 +76 -22
- package/dist/node/index.mjs +77 -23
- package/dist/node/node.cjs +76 -22
- package/dist/node/node.mjs +77 -23
- 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
package/dist/browser/index.cjs
CHANGED
|
@@ -525,12 +525,12 @@ async function ensureRuntimeFactoriesRegistered(registry = factory.Registry) {
|
|
|
525
525
|
}
|
|
526
526
|
|
|
527
527
|
// This file is auto-generated during build - do not edit manually
|
|
528
|
-
// Generated from package.json version: 0.4.
|
|
528
|
+
// Generated from package.json version: 0.4.5
|
|
529
529
|
/**
|
|
530
530
|
* The package version, injected at build time.
|
|
531
531
|
* @internal
|
|
532
532
|
*/
|
|
533
|
-
const VERSION = '0.4.
|
|
533
|
+
const VERSION = '0.4.5';
|
|
534
534
|
|
|
535
535
|
let initialized = false;
|
|
536
536
|
const runtimePlugin = {
|
|
@@ -22062,13 +22062,21 @@ function normalizeConfig$w(config) {
|
|
|
22062
22062
|
return { profile: canonicalProfile };
|
|
22063
22063
|
}
|
|
22064
22064
|
function resolveProfileName$2(candidate) {
|
|
22065
|
-
|
|
22065
|
+
let direct = coerceProfileString$2(candidate.profile);
|
|
22066
|
+
if (direct && factory.ExpressionEvaluator.isExpression(direct)) {
|
|
22067
|
+
const evaluated = factory.ExpressionEvaluator.evaluate(direct);
|
|
22068
|
+
direct = coerceProfileString$2(evaluated);
|
|
22069
|
+
}
|
|
22066
22070
|
if (direct) {
|
|
22067
22071
|
return direct;
|
|
22068
22072
|
}
|
|
22069
22073
|
const legacyKeys = ['profile_name', 'profileName'];
|
|
22070
22074
|
for (const legacyKey of legacyKeys) {
|
|
22071
|
-
|
|
22075
|
+
let legacyValue = coerceProfileString$2(candidate[legacyKey]);
|
|
22076
|
+
if (legacyValue && factory.ExpressionEvaluator.isExpression(legacyValue)) {
|
|
22077
|
+
const evaluated = factory.ExpressionEvaluator.evaluate(legacyValue);
|
|
22078
|
+
legacyValue = coerceProfileString$2(evaluated);
|
|
22079
|
+
}
|
|
22072
22080
|
if (legacyValue) {
|
|
22073
22081
|
return legacyValue;
|
|
22074
22082
|
}
|
|
@@ -22676,6 +22684,7 @@ class BasicAuthorizationPolicy {
|
|
|
22676
22684
|
// Action must be explicitly provided; default to wildcard if omitted
|
|
22677
22685
|
// for backward compatibility during transition
|
|
22678
22686
|
const resolvedAction = action ?? '*';
|
|
22687
|
+
const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
|
|
22679
22688
|
const address = extractAddress(envelope);
|
|
22680
22689
|
const grantedScopes = extractGrantedScopes(context);
|
|
22681
22690
|
const rawFrameType = envelope.frame
|
|
@@ -22685,8 +22694,8 @@ class BasicAuthorizationPolicy {
|
|
|
22685
22694
|
: '';
|
|
22686
22695
|
// Extract and normalize origin type for rule matching
|
|
22687
22696
|
const rawOriginType = context?.originType;
|
|
22688
|
-
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
22689
|
-
?
|
|
22697
|
+
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
22698
|
+
? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
|
|
22690
22699
|
: undefined;
|
|
22691
22700
|
const evaluationTrace = [];
|
|
22692
22701
|
// Evaluate rules in order (first match wins)
|
|
@@ -22733,8 +22742,8 @@ class BasicAuthorizationPolicy {
|
|
|
22733
22742
|
}
|
|
22734
22743
|
}
|
|
22735
22744
|
// Check action match
|
|
22736
|
-
if (!rule.actions.has('*') && !rule.actions.has(
|
|
22737
|
-
step.expression = `action: ${
|
|
22745
|
+
if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
|
|
22746
|
+
step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
|
|
22738
22747
|
step.result = false;
|
|
22739
22748
|
evaluationTrace.push(step);
|
|
22740
22749
|
continue;
|
|
@@ -22801,6 +22810,9 @@ class BasicAuthorizationPolicy {
|
|
|
22801
22810
|
};
|
|
22802
22811
|
}
|
|
22803
22812
|
validateDefaultEffect(effect) {
|
|
22813
|
+
if (effect === undefined || effect === null) {
|
|
22814
|
+
return 'deny';
|
|
22815
|
+
}
|
|
22804
22816
|
if (effect !== 'allow' && effect !== 'deny') {
|
|
22805
22817
|
throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
|
|
22806
22818
|
}
|
|
@@ -22873,10 +22885,11 @@ class BasicAuthorizationPolicy {
|
|
|
22873
22885
|
}
|
|
22874
22886
|
// Handle single action
|
|
22875
22887
|
if (typeof action === 'string') {
|
|
22876
|
-
|
|
22888
|
+
const normalized = this.normalizeActionToken(action);
|
|
22889
|
+
if (!normalized) {
|
|
22877
22890
|
throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
|
|
22878
22891
|
}
|
|
22879
|
-
return new Set([
|
|
22892
|
+
return new Set([normalized]);
|
|
22880
22893
|
}
|
|
22881
22894
|
// Handle array of actions
|
|
22882
22895
|
if (!Array.isArray(action)) {
|
|
@@ -22890,10 +22903,11 @@ class BasicAuthorizationPolicy {
|
|
|
22890
22903
|
if (typeof a !== 'string') {
|
|
22891
22904
|
throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
|
|
22892
22905
|
}
|
|
22893
|
-
|
|
22906
|
+
const normalized = this.normalizeActionToken(a);
|
|
22907
|
+
if (!normalized) {
|
|
22894
22908
|
throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
|
|
22895
22909
|
}
|
|
22896
|
-
actions.add(
|
|
22910
|
+
actions.add(normalized);
|
|
22897
22911
|
}
|
|
22898
22912
|
return actions;
|
|
22899
22913
|
}
|
|
@@ -22996,11 +23010,12 @@ class BasicAuthorizationPolicy {
|
|
|
22996
23010
|
}
|
|
22997
23011
|
// Handle single origin type
|
|
22998
23012
|
if (typeof originType === 'string') {
|
|
22999
|
-
const
|
|
23000
|
-
if (!
|
|
23013
|
+
const trimmed = originType.trim();
|
|
23014
|
+
if (!trimmed) {
|
|
23001
23015
|
throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
|
|
23002
23016
|
}
|
|
23003
|
-
|
|
23017
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
23018
|
+
if (!normalized) {
|
|
23004
23019
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
|
|
23005
23020
|
}
|
|
23006
23021
|
return new Set([normalized]);
|
|
@@ -23017,17 +23032,50 @@ class BasicAuthorizationPolicy {
|
|
|
23017
23032
|
if (typeof ot !== 'string') {
|
|
23018
23033
|
throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
|
|
23019
23034
|
}
|
|
23020
|
-
const
|
|
23021
|
-
if (!
|
|
23035
|
+
const trimmed = ot.trim();
|
|
23036
|
+
if (!trimmed) {
|
|
23022
23037
|
throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
|
|
23023
23038
|
}
|
|
23024
|
-
|
|
23039
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
23040
|
+
if (!normalized) {
|
|
23025
23041
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
|
|
23026
23042
|
}
|
|
23027
23043
|
originTypes.add(normalized);
|
|
23028
23044
|
}
|
|
23029
23045
|
return originTypes;
|
|
23030
23046
|
}
|
|
23047
|
+
normalizeActionToken(value) {
|
|
23048
|
+
const trimmed = value.trim();
|
|
23049
|
+
if (!trimmed) {
|
|
23050
|
+
return null;
|
|
23051
|
+
}
|
|
23052
|
+
if (trimmed === '*') {
|
|
23053
|
+
return '*';
|
|
23054
|
+
}
|
|
23055
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
23056
|
+
const map = {
|
|
23057
|
+
connect: 'Connect',
|
|
23058
|
+
forwardupstream: 'ForwardUpstream',
|
|
23059
|
+
forwarddownstream: 'ForwardDownstream',
|
|
23060
|
+
forwardpeer: 'ForwardPeer',
|
|
23061
|
+
deliverlocal: 'DeliverLocal',
|
|
23062
|
+
};
|
|
23063
|
+
return map[normalized] ?? null;
|
|
23064
|
+
}
|
|
23065
|
+
normalizeOriginTypeToken(value) {
|
|
23066
|
+
const trimmed = value.trim();
|
|
23067
|
+
if (!trimmed) {
|
|
23068
|
+
return null;
|
|
23069
|
+
}
|
|
23070
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
23071
|
+
const map = {
|
|
23072
|
+
downstream: 'downstream',
|
|
23073
|
+
upstream: 'upstream',
|
|
23074
|
+
peer: 'peer',
|
|
23075
|
+
local: 'local',
|
|
23076
|
+
};
|
|
23077
|
+
return map[normalized] ?? null;
|
|
23078
|
+
}
|
|
23031
23079
|
}
|
|
23032
23080
|
|
|
23033
23081
|
var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
|
|
@@ -42776,16 +42824,22 @@ class LocalFileAuthorizationPolicySource {
|
|
|
42776
42824
|
const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
|
|
42777
42825
|
// Ensure we have a type field for the factory
|
|
42778
42826
|
if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
|
|
42779
|
-
|
|
42780
|
-
|
|
42827
|
+
logger$1.warning('policy_type_missing_defaulting_to_basic', {
|
|
42828
|
+
path: this.path,
|
|
42829
|
+
});
|
|
42830
|
+
factoryConfig.type =
|
|
42831
|
+
'BasicAuthorizationPolicy';
|
|
42781
42832
|
}
|
|
42782
42833
|
// Build the factory config with the policy definition
|
|
42783
42834
|
// The file content IS the policy definition, so we extract the type
|
|
42784
42835
|
// and wrap the remaining content as the policyDefinition
|
|
42785
|
-
const { type, ...restOfFile } = policyDefinition;
|
|
42836
|
+
const { type: fileType, ...restOfFile } = policyDefinition;
|
|
42837
|
+
const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
|
|
42838
|
+
? fileType
|
|
42839
|
+
: factoryConfig.type;
|
|
42786
42840
|
const mergedConfig = this.policyFactoryConfig != null
|
|
42787
42841
|
? { ...this.policyFactoryConfig, policyDefinition }
|
|
42788
|
-
: { type:
|
|
42842
|
+
: { type: resolvedType, policyDefinition: restOfFile };
|
|
42789
42843
|
// Create the policy using the factory system
|
|
42790
42844
|
const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
|
|
42791
42845
|
if (!policy) {
|
package/dist/browser/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { parseAddressComponents, FlowFlags, FameAddress, DEFAULT_POLLING_TIMEOUT_MS, extractEnvelopeAndContext, createChannelMessage, generateId, createFameEnvelope, parseAddress, formatAddress, formatAddressFromComponents, FameResponseType, localDeliveryContext, Binding, DeliveryOriginType, makeResponse, isFameMessageResponse, parseRequest, makeRequest, DEFAULT_INVOKE_TIMEOUT_MILLIS, parseResponse, ConnectorState, ConnectorStateUtils, FameFabric, isFameMessageService, isFameRPCService, FameServiceProxy, generateIdAsync, snakeToCamelObject, getDefaultFameConfigResolver, setDefaultFameConfigResolver, SigningMaterial, AuthorizationContextSchema, FameDeliveryContextSchema, SecurityContextSchema, withFabric, FameEnvelopeSchema, deserializeEnvelope, FameChannelMessage, SINK_CAPABILITY, FameFabricFactory, serializeEnvelope, createAuthorizationContext } from '@naylence/core';
|
|
2
2
|
export * from '@naylence/core';
|
|
3
3
|
import { z, ZodError } from 'zod';
|
|
4
|
-
import { Registry, AbstractResourceFactory, createResource as createResource$1, createDefaultResource, registerFactory, Expressions, ExtensionManager, ExpressionEvaluationPolicy, configValidator } from '@naylence/factory';
|
|
4
|
+
import { Registry, AbstractResourceFactory, createResource as createResource$1, createDefaultResource, registerFactory, Expressions, ExtensionManager, ExpressionEvaluationPolicy, ExpressionEvaluator, configValidator } from '@naylence/factory';
|
|
5
5
|
import { sign, hashes, verify } from '@noble/ed25519';
|
|
6
6
|
import { sha256, sha512 } from '@noble/hashes/sha2.js';
|
|
7
7
|
import { chacha20poly1305 } from '@noble/ciphers/chacha.js';
|
|
@@ -523,12 +523,12 @@ async function ensureRuntimeFactoriesRegistered(registry = Registry) {
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
// This file is auto-generated during build - do not edit manually
|
|
526
|
-
// Generated from package.json version: 0.4.
|
|
526
|
+
// Generated from package.json version: 0.4.5
|
|
527
527
|
/**
|
|
528
528
|
* The package version, injected at build time.
|
|
529
529
|
* @internal
|
|
530
530
|
*/
|
|
531
|
-
const VERSION = '0.4.
|
|
531
|
+
const VERSION = '0.4.5';
|
|
532
532
|
|
|
533
533
|
let initialized = false;
|
|
534
534
|
const runtimePlugin = {
|
|
@@ -22060,13 +22060,21 @@ function normalizeConfig$w(config) {
|
|
|
22060
22060
|
return { profile: canonicalProfile };
|
|
22061
22061
|
}
|
|
22062
22062
|
function resolveProfileName$2(candidate) {
|
|
22063
|
-
|
|
22063
|
+
let direct = coerceProfileString$2(candidate.profile);
|
|
22064
|
+
if (direct && ExpressionEvaluator.isExpression(direct)) {
|
|
22065
|
+
const evaluated = ExpressionEvaluator.evaluate(direct);
|
|
22066
|
+
direct = coerceProfileString$2(evaluated);
|
|
22067
|
+
}
|
|
22064
22068
|
if (direct) {
|
|
22065
22069
|
return direct;
|
|
22066
22070
|
}
|
|
22067
22071
|
const legacyKeys = ['profile_name', 'profileName'];
|
|
22068
22072
|
for (const legacyKey of legacyKeys) {
|
|
22069
|
-
|
|
22073
|
+
let legacyValue = coerceProfileString$2(candidate[legacyKey]);
|
|
22074
|
+
if (legacyValue && ExpressionEvaluator.isExpression(legacyValue)) {
|
|
22075
|
+
const evaluated = ExpressionEvaluator.evaluate(legacyValue);
|
|
22076
|
+
legacyValue = coerceProfileString$2(evaluated);
|
|
22077
|
+
}
|
|
22070
22078
|
if (legacyValue) {
|
|
22071
22079
|
return legacyValue;
|
|
22072
22080
|
}
|
|
@@ -22674,6 +22682,7 @@ class BasicAuthorizationPolicy {
|
|
|
22674
22682
|
// Action must be explicitly provided; default to wildcard if omitted
|
|
22675
22683
|
// for backward compatibility during transition
|
|
22676
22684
|
const resolvedAction = action ?? '*';
|
|
22685
|
+
const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
|
|
22677
22686
|
const address = extractAddress(envelope);
|
|
22678
22687
|
const grantedScopes = extractGrantedScopes(context);
|
|
22679
22688
|
const rawFrameType = envelope.frame
|
|
@@ -22683,8 +22692,8 @@ class BasicAuthorizationPolicy {
|
|
|
22683
22692
|
: '';
|
|
22684
22693
|
// Extract and normalize origin type for rule matching
|
|
22685
22694
|
const rawOriginType = context?.originType;
|
|
22686
|
-
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
22687
|
-
?
|
|
22695
|
+
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
22696
|
+
? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
|
|
22688
22697
|
: undefined;
|
|
22689
22698
|
const evaluationTrace = [];
|
|
22690
22699
|
// Evaluate rules in order (first match wins)
|
|
@@ -22731,8 +22740,8 @@ class BasicAuthorizationPolicy {
|
|
|
22731
22740
|
}
|
|
22732
22741
|
}
|
|
22733
22742
|
// Check action match
|
|
22734
|
-
if (!rule.actions.has('*') && !rule.actions.has(
|
|
22735
|
-
step.expression = `action: ${
|
|
22743
|
+
if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
|
|
22744
|
+
step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
|
|
22736
22745
|
step.result = false;
|
|
22737
22746
|
evaluationTrace.push(step);
|
|
22738
22747
|
continue;
|
|
@@ -22799,6 +22808,9 @@ class BasicAuthorizationPolicy {
|
|
|
22799
22808
|
};
|
|
22800
22809
|
}
|
|
22801
22810
|
validateDefaultEffect(effect) {
|
|
22811
|
+
if (effect === undefined || effect === null) {
|
|
22812
|
+
return 'deny';
|
|
22813
|
+
}
|
|
22802
22814
|
if (effect !== 'allow' && effect !== 'deny') {
|
|
22803
22815
|
throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
|
|
22804
22816
|
}
|
|
@@ -22871,10 +22883,11 @@ class BasicAuthorizationPolicy {
|
|
|
22871
22883
|
}
|
|
22872
22884
|
// Handle single action
|
|
22873
22885
|
if (typeof action === 'string') {
|
|
22874
|
-
|
|
22886
|
+
const normalized = this.normalizeActionToken(action);
|
|
22887
|
+
if (!normalized) {
|
|
22875
22888
|
throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
|
|
22876
22889
|
}
|
|
22877
|
-
return new Set([
|
|
22890
|
+
return new Set([normalized]);
|
|
22878
22891
|
}
|
|
22879
22892
|
// Handle array of actions
|
|
22880
22893
|
if (!Array.isArray(action)) {
|
|
@@ -22888,10 +22901,11 @@ class BasicAuthorizationPolicy {
|
|
|
22888
22901
|
if (typeof a !== 'string') {
|
|
22889
22902
|
throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
|
|
22890
22903
|
}
|
|
22891
|
-
|
|
22904
|
+
const normalized = this.normalizeActionToken(a);
|
|
22905
|
+
if (!normalized) {
|
|
22892
22906
|
throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${VALID_ACTIONS.join(', ')}`);
|
|
22893
22907
|
}
|
|
22894
|
-
actions.add(
|
|
22908
|
+
actions.add(normalized);
|
|
22895
22909
|
}
|
|
22896
22910
|
return actions;
|
|
22897
22911
|
}
|
|
@@ -22994,11 +23008,12 @@ class BasicAuthorizationPolicy {
|
|
|
22994
23008
|
}
|
|
22995
23009
|
// Handle single origin type
|
|
22996
23010
|
if (typeof originType === 'string') {
|
|
22997
|
-
const
|
|
22998
|
-
if (!
|
|
23011
|
+
const trimmed = originType.trim();
|
|
23012
|
+
if (!trimmed) {
|
|
22999
23013
|
throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
|
|
23000
23014
|
}
|
|
23001
|
-
|
|
23015
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
23016
|
+
if (!normalized) {
|
|
23002
23017
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
|
|
23003
23018
|
}
|
|
23004
23019
|
return new Set([normalized]);
|
|
@@ -23015,17 +23030,50 @@ class BasicAuthorizationPolicy {
|
|
|
23015
23030
|
if (typeof ot !== 'string') {
|
|
23016
23031
|
throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
|
|
23017
23032
|
}
|
|
23018
|
-
const
|
|
23019
|
-
if (!
|
|
23033
|
+
const trimmed = ot.trim();
|
|
23034
|
+
if (!trimmed) {
|
|
23020
23035
|
throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
|
|
23021
23036
|
}
|
|
23022
|
-
|
|
23037
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
23038
|
+
if (!normalized) {
|
|
23023
23039
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${VALID_ORIGIN_TYPES.join(', ')}`);
|
|
23024
23040
|
}
|
|
23025
23041
|
originTypes.add(normalized);
|
|
23026
23042
|
}
|
|
23027
23043
|
return originTypes;
|
|
23028
23044
|
}
|
|
23045
|
+
normalizeActionToken(value) {
|
|
23046
|
+
const trimmed = value.trim();
|
|
23047
|
+
if (!trimmed) {
|
|
23048
|
+
return null;
|
|
23049
|
+
}
|
|
23050
|
+
if (trimmed === '*') {
|
|
23051
|
+
return '*';
|
|
23052
|
+
}
|
|
23053
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
23054
|
+
const map = {
|
|
23055
|
+
connect: 'Connect',
|
|
23056
|
+
forwardupstream: 'ForwardUpstream',
|
|
23057
|
+
forwarddownstream: 'ForwardDownstream',
|
|
23058
|
+
forwardpeer: 'ForwardPeer',
|
|
23059
|
+
deliverlocal: 'DeliverLocal',
|
|
23060
|
+
};
|
|
23061
|
+
return map[normalized] ?? null;
|
|
23062
|
+
}
|
|
23063
|
+
normalizeOriginTypeToken(value) {
|
|
23064
|
+
const trimmed = value.trim();
|
|
23065
|
+
if (!trimmed) {
|
|
23066
|
+
return null;
|
|
23067
|
+
}
|
|
23068
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
23069
|
+
const map = {
|
|
23070
|
+
downstream: 'downstream',
|
|
23071
|
+
upstream: 'upstream',
|
|
23072
|
+
peer: 'peer',
|
|
23073
|
+
local: 'local',
|
|
23074
|
+
};
|
|
23075
|
+
return map[normalized] ?? null;
|
|
23076
|
+
}
|
|
23029
23077
|
}
|
|
23030
23078
|
|
|
23031
23079
|
var basicAuthorizationPolicy = /*#__PURE__*/Object.freeze({
|
|
@@ -42774,16 +42822,22 @@ class LocalFileAuthorizationPolicySource {
|
|
|
42774
42822
|
const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
|
|
42775
42823
|
// Ensure we have a type field for the factory
|
|
42776
42824
|
if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
|
|
42777
|
-
|
|
42778
|
-
|
|
42825
|
+
logger$1.warning('policy_type_missing_defaulting_to_basic', {
|
|
42826
|
+
path: this.path,
|
|
42827
|
+
});
|
|
42828
|
+
factoryConfig.type =
|
|
42829
|
+
'BasicAuthorizationPolicy';
|
|
42779
42830
|
}
|
|
42780
42831
|
// Build the factory config with the policy definition
|
|
42781
42832
|
// The file content IS the policy definition, so we extract the type
|
|
42782
42833
|
// and wrap the remaining content as the policyDefinition
|
|
42783
|
-
const { type, ...restOfFile } = policyDefinition;
|
|
42834
|
+
const { type: fileType, ...restOfFile } = policyDefinition;
|
|
42835
|
+
const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
|
|
42836
|
+
? fileType
|
|
42837
|
+
: factoryConfig.type;
|
|
42784
42838
|
const mergedConfig = this.policyFactoryConfig != null
|
|
42785
42839
|
? { ...this.policyFactoryConfig, policyDefinition }
|
|
42786
|
-
: { type:
|
|
42840
|
+
: { type: resolvedType, policyDefinition: restOfFile };
|
|
42787
42841
|
// Create the policy using the factory system
|
|
42788
42842
|
const policy = await AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
|
|
42789
42843
|
if (!policy) {
|
|
@@ -146,13 +146,21 @@ function normalizeConfig(config) {
|
|
|
146
146
|
return { profile: canonicalProfile };
|
|
147
147
|
}
|
|
148
148
|
function resolveProfileName(candidate) {
|
|
149
|
-
|
|
149
|
+
let direct = coerceProfileString(candidate.profile);
|
|
150
|
+
if (direct && factory_1.ExpressionEvaluator.isExpression(direct)) {
|
|
151
|
+
const evaluated = factory_1.ExpressionEvaluator.evaluate(direct);
|
|
152
|
+
direct = coerceProfileString(evaluated);
|
|
153
|
+
}
|
|
150
154
|
if (direct) {
|
|
151
155
|
return direct;
|
|
152
156
|
}
|
|
153
157
|
const legacyKeys = ['profile_name', 'profileName'];
|
|
154
158
|
for (const legacyKey of legacyKeys) {
|
|
155
|
-
|
|
159
|
+
let legacyValue = coerceProfileString(candidate[legacyKey]);
|
|
160
|
+
if (legacyValue && factory_1.ExpressionEvaluator.isExpression(legacyValue)) {
|
|
161
|
+
const evaluated = factory_1.ExpressionEvaluator.evaluate(legacyValue);
|
|
162
|
+
legacyValue = coerceProfileString(evaluated);
|
|
163
|
+
}
|
|
156
164
|
if (legacyValue) {
|
|
157
165
|
return legacyValue;
|
|
158
166
|
}
|
|
@@ -93,6 +93,7 @@ class BasicAuthorizationPolicy {
|
|
|
93
93
|
// Action must be explicitly provided; default to wildcard if omitted
|
|
94
94
|
// for backward compatibility during transition
|
|
95
95
|
const resolvedAction = action ?? '*';
|
|
96
|
+
const resolvedActionNormalized = this.normalizeActionToken(resolvedAction) ?? resolvedAction;
|
|
96
97
|
const address = extractAddress(envelope);
|
|
97
98
|
const grantedScopes = extractGrantedScopes(context);
|
|
98
99
|
const rawFrameType = envelope.frame
|
|
@@ -102,8 +103,8 @@ class BasicAuthorizationPolicy {
|
|
|
102
103
|
: '';
|
|
103
104
|
// Extract and normalize origin type for rule matching
|
|
104
105
|
const rawOriginType = context?.originType;
|
|
105
|
-
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
106
|
-
?
|
|
106
|
+
const originTypeNormalized = typeof rawOriginType === 'string'
|
|
107
|
+
? this.normalizeOriginTypeToken(rawOriginType) ?? undefined
|
|
107
108
|
: undefined;
|
|
108
109
|
const evaluationTrace = [];
|
|
109
110
|
// Evaluate rules in order (first match wins)
|
|
@@ -150,8 +151,8 @@ class BasicAuthorizationPolicy {
|
|
|
150
151
|
}
|
|
151
152
|
}
|
|
152
153
|
// Check action match
|
|
153
|
-
if (!rule.actions.has('*') && !rule.actions.has(
|
|
154
|
-
step.expression = `action: ${
|
|
154
|
+
if (!rule.actions.has('*') && !rule.actions.has(resolvedActionNormalized)) {
|
|
155
|
+
step.expression = `action: ${resolvedActionNormalized} not in [${Array.from(rule.actions).join(', ')}]`;
|
|
155
156
|
step.result = false;
|
|
156
157
|
evaluationTrace.push(step);
|
|
157
158
|
continue;
|
|
@@ -218,6 +219,9 @@ class BasicAuthorizationPolicy {
|
|
|
218
219
|
};
|
|
219
220
|
}
|
|
220
221
|
validateDefaultEffect(effect) {
|
|
222
|
+
if (effect === undefined || effect === null) {
|
|
223
|
+
return 'deny';
|
|
224
|
+
}
|
|
221
225
|
if (effect !== 'allow' && effect !== 'deny') {
|
|
222
226
|
throw new Error(`Invalid default_effect: "${String(effect)}". Must be "allow" or "deny"`);
|
|
223
227
|
}
|
|
@@ -290,10 +294,11 @@ class BasicAuthorizationPolicy {
|
|
|
290
294
|
}
|
|
291
295
|
// Handle single action
|
|
292
296
|
if (typeof action === 'string') {
|
|
293
|
-
|
|
297
|
+
const normalized = this.normalizeActionToken(action);
|
|
298
|
+
if (!normalized) {
|
|
294
299
|
throw new Error(`Invalid action in rule "${ruleId}": "${action}". Must be one of: ${authorization_policy_definition_js_1.VALID_ACTIONS.join(', ')}`);
|
|
295
300
|
}
|
|
296
|
-
return new Set([
|
|
301
|
+
return new Set([normalized]);
|
|
297
302
|
}
|
|
298
303
|
// Handle array of actions
|
|
299
304
|
if (!Array.isArray(action)) {
|
|
@@ -307,10 +312,11 @@ class BasicAuthorizationPolicy {
|
|
|
307
312
|
if (typeof a !== 'string') {
|
|
308
313
|
throw new Error(`Invalid action in rule "${ruleId}": all values must be strings`);
|
|
309
314
|
}
|
|
310
|
-
|
|
315
|
+
const normalized = this.normalizeActionToken(a);
|
|
316
|
+
if (!normalized) {
|
|
311
317
|
throw new Error(`Invalid action in rule "${ruleId}": "${a}". Must be one of: ${authorization_policy_definition_js_1.VALID_ACTIONS.join(', ')}`);
|
|
312
318
|
}
|
|
313
|
-
actions.add(
|
|
319
|
+
actions.add(normalized);
|
|
314
320
|
}
|
|
315
321
|
return actions;
|
|
316
322
|
}
|
|
@@ -413,11 +419,12 @@ class BasicAuthorizationPolicy {
|
|
|
413
419
|
}
|
|
414
420
|
// Handle single origin type
|
|
415
421
|
if (typeof originType === 'string') {
|
|
416
|
-
const
|
|
417
|
-
if (!
|
|
422
|
+
const trimmed = originType.trim();
|
|
423
|
+
if (!trimmed) {
|
|
418
424
|
throw new Error(`Invalid origin_type in rule "${ruleId}": value must not be empty`);
|
|
419
425
|
}
|
|
420
|
-
|
|
426
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
427
|
+
if (!normalized) {
|
|
421
428
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${originType}". Must be one of: ${authorization_policy_definition_js_1.VALID_ORIGIN_TYPES.join(', ')}`);
|
|
422
429
|
}
|
|
423
430
|
return new Set([normalized]);
|
|
@@ -434,16 +441,49 @@ class BasicAuthorizationPolicy {
|
|
|
434
441
|
if (typeof ot !== 'string') {
|
|
435
442
|
throw new Error(`Invalid origin_type in rule "${ruleId}": all values must be strings`);
|
|
436
443
|
}
|
|
437
|
-
const
|
|
438
|
-
if (!
|
|
444
|
+
const trimmed = ot.trim();
|
|
445
|
+
if (!trimmed) {
|
|
439
446
|
throw new Error(`Invalid origin_type in rule "${ruleId}": values must not be empty`);
|
|
440
447
|
}
|
|
441
|
-
|
|
448
|
+
const normalized = this.normalizeOriginTypeToken(trimmed);
|
|
449
|
+
if (!normalized) {
|
|
442
450
|
throw new Error(`Invalid origin_type in rule "${ruleId}": "${ot}". Must be one of: ${authorization_policy_definition_js_1.VALID_ORIGIN_TYPES.join(', ')}`);
|
|
443
451
|
}
|
|
444
452
|
originTypes.add(normalized);
|
|
445
453
|
}
|
|
446
454
|
return originTypes;
|
|
447
455
|
}
|
|
456
|
+
normalizeActionToken(value) {
|
|
457
|
+
const trimmed = value.trim();
|
|
458
|
+
if (!trimmed) {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
if (trimmed === '*') {
|
|
462
|
+
return '*';
|
|
463
|
+
}
|
|
464
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
465
|
+
const map = {
|
|
466
|
+
connect: 'Connect',
|
|
467
|
+
forwardupstream: 'ForwardUpstream',
|
|
468
|
+
forwarddownstream: 'ForwardDownstream',
|
|
469
|
+
forwardpeer: 'ForwardPeer',
|
|
470
|
+
deliverlocal: 'DeliverLocal',
|
|
471
|
+
};
|
|
472
|
+
return map[normalized] ?? null;
|
|
473
|
+
}
|
|
474
|
+
normalizeOriginTypeToken(value) {
|
|
475
|
+
const trimmed = value.trim();
|
|
476
|
+
if (!trimmed) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
const normalized = trimmed.replace(/[\s_-]+/g, '').toLowerCase();
|
|
480
|
+
const map = {
|
|
481
|
+
downstream: 'downstream',
|
|
482
|
+
upstream: 'upstream',
|
|
483
|
+
peer: 'peer',
|
|
484
|
+
local: 'local',
|
|
485
|
+
};
|
|
486
|
+
return map[normalized] ?? null;
|
|
487
|
+
}
|
|
448
488
|
}
|
|
449
489
|
exports.BasicAuthorizationPolicy = BasicAuthorizationPolicy;
|
package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js
CHANGED
|
@@ -123,16 +123,22 @@ class LocalFileAuthorizationPolicySource {
|
|
|
123
123
|
const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
|
|
124
124
|
// Ensure we have a type field for the factory
|
|
125
125
|
if (!('type' in factoryConfig) || typeof factoryConfig.type !== 'string') {
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
logger.warning('policy_type_missing_defaulting_to_basic', {
|
|
127
|
+
path: this.path,
|
|
128
|
+
});
|
|
129
|
+
factoryConfig.type =
|
|
130
|
+
'BasicAuthorizationPolicy';
|
|
128
131
|
}
|
|
129
132
|
// Build the factory config with the policy definition
|
|
130
133
|
// The file content IS the policy definition, so we extract the type
|
|
131
134
|
// and wrap the remaining content as the policyDefinition
|
|
132
|
-
const { type, ...restOfFile } = policyDefinition;
|
|
135
|
+
const { type: fileType, ...restOfFile } = policyDefinition;
|
|
136
|
+
const resolvedType = typeof fileType === 'string' && fileType.trim().length > 0
|
|
137
|
+
? fileType
|
|
138
|
+
: factoryConfig.type;
|
|
133
139
|
const mergedConfig = this.policyFactoryConfig != null
|
|
134
140
|
? { ...this.policyFactoryConfig, policyDefinition }
|
|
135
|
-
: { type:
|
|
141
|
+
: { type: resolvedType, policyDefinition: restOfFile };
|
|
136
142
|
// Create the policy using the factory system
|
|
137
143
|
const policy = await authorization_policy_factory_js_1.AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
|
|
138
144
|
if (!policy) {
|
package/dist/cjs/version.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// This file is auto-generated during build - do not edit manually
|
|
3
|
-
// Generated from package.json version: 0.4.
|
|
3
|
+
// Generated from package.json version: 0.4.5
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
5
|
exports.VERSION = void 0;
|
|
6
6
|
/**
|
|
7
7
|
* The package version, injected at build time.
|
|
8
8
|
* @internal
|
|
9
9
|
*/
|
|
10
|
-
exports.VERSION = '0.4.
|
|
10
|
+
exports.VERSION = '0.4.5';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Expressions } from '@naylence/factory';
|
|
1
|
+
import { Expressions, ExpressionEvaluator } from '@naylence/factory';
|
|
2
2
|
import { getLogger } from '../../util/logging.js';
|
|
3
3
|
import { AUTHORIZER_FACTORY_BASE_TYPE, AuthorizerFactory, } from './authorizer-factory.js';
|
|
4
4
|
const logger = getLogger('naylence.fame.security.auth.authorization_profile_factory');
|
|
@@ -142,13 +142,21 @@ function normalizeConfig(config) {
|
|
|
142
142
|
return { profile: canonicalProfile };
|
|
143
143
|
}
|
|
144
144
|
function resolveProfileName(candidate) {
|
|
145
|
-
|
|
145
|
+
let direct = coerceProfileString(candidate.profile);
|
|
146
|
+
if (direct && ExpressionEvaluator.isExpression(direct)) {
|
|
147
|
+
const evaluated = ExpressionEvaluator.evaluate(direct);
|
|
148
|
+
direct = coerceProfileString(evaluated);
|
|
149
|
+
}
|
|
146
150
|
if (direct) {
|
|
147
151
|
return direct;
|
|
148
152
|
}
|
|
149
153
|
const legacyKeys = ['profile_name', 'profileName'];
|
|
150
154
|
for (const legacyKey of legacyKeys) {
|
|
151
|
-
|
|
155
|
+
let legacyValue = coerceProfileString(candidate[legacyKey]);
|
|
156
|
+
if (legacyValue && ExpressionEvaluator.isExpression(legacyValue)) {
|
|
157
|
+
const evaluated = ExpressionEvaluator.evaluate(legacyValue);
|
|
158
|
+
legacyValue = coerceProfileString(evaluated);
|
|
159
|
+
}
|
|
152
160
|
if (legacyValue) {
|
|
153
161
|
return legacyValue;
|
|
154
162
|
}
|