@naylence/runtime 0.3.21 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/browser/index.cjs +3368 -1393
  2. package/dist/browser/index.mjs +3324 -1387
  3. package/dist/cjs/naylence/fame/factory-manifest.js +8 -0
  4. package/dist/cjs/naylence/fame/node/node-event-listener.js +4 -0
  5. package/dist/cjs/naylence/fame/security/auth/authorization-profile-factory.js +165 -0
  6. package/dist/cjs/naylence/fame/security/auth/default-policy-authorizer-factory.js +147 -0
  7. package/dist/cjs/naylence/fame/security/auth/default-policy-authorizer.js +291 -0
  8. package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
  9. package/dist/cjs/naylence/fame/security/auth/oauth2-authorizer.js +19 -4
  10. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-definition.js +60 -0
  11. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-factory.js +35 -0
  12. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-source-factory.js +35 -0
  13. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy-source.js +2 -0
  14. package/dist/cjs/naylence/fame/security/auth/policy/authorization-policy.js +2 -0
  15. package/dist/cjs/naylence/fame/security/auth/policy/basic-authorization-policy-factory.js +99 -0
  16. package/dist/cjs/naylence/fame/security/auth/policy/basic-authorization-policy.js +449 -0
  17. package/dist/cjs/naylence/fame/security/auth/policy/index.js +40 -0
  18. package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.js +101 -0
  19. package/dist/cjs/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +164 -0
  20. package/dist/cjs/naylence/fame/security/auth/policy/pattern-matcher.js +195 -0
  21. package/dist/cjs/naylence/fame/security/auth/policy/scope-matcher.js +169 -0
  22. package/dist/cjs/naylence/fame/security/auth/policy-authorizer.js +2 -0
  23. package/dist/cjs/naylence/fame/security/default-security-manager.js +94 -0
  24. package/dist/cjs/naylence/fame/security/index.js +22 -1
  25. package/dist/cjs/naylence/fame/security/node-security-profile-factory.js +15 -73
  26. package/dist/cjs/naylence/fame/sentinel/router.js +67 -1
  27. package/dist/cjs/naylence/fame/sentinel/sentinel.js +46 -2
  28. package/dist/cjs/naylence/fame/util/register-runtime-factories.js +2 -0
  29. package/dist/cjs/version.js +2 -2
  30. package/dist/esm/naylence/fame/factory-manifest.js +8 -0
  31. package/dist/esm/naylence/fame/node/node-event-listener.js +4 -0
  32. package/dist/esm/naylence/fame/security/auth/authorization-profile-factory.js +161 -0
  33. package/dist/esm/naylence/fame/security/auth/default-policy-authorizer-factory.js +110 -0
  34. package/dist/esm/naylence/fame/security/auth/default-policy-authorizer.js +287 -0
  35. package/dist/esm/naylence/fame/security/auth/oauth2-authorizer-factory.js +7 -0
  36. package/dist/esm/naylence/fame/security/auth/oauth2-authorizer.js +19 -4
  37. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-definition.js +57 -0
  38. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-factory.js +31 -0
  39. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-source-factory.js +31 -0
  40. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy-source.js +1 -0
  41. package/dist/esm/naylence/fame/security/auth/policy/authorization-policy.js +1 -0
  42. package/dist/esm/naylence/fame/security/auth/policy/basic-authorization-policy-factory.js +62 -0
  43. package/dist/esm/naylence/fame/security/auth/policy/basic-authorization-policy.js +445 -0
  44. package/dist/esm/naylence/fame/security/auth/policy/index.js +20 -0
  45. package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.js +64 -0
  46. package/dist/esm/naylence/fame/security/auth/policy/local-file-authorization-policy-source.js +127 -0
  47. package/dist/esm/naylence/fame/security/auth/policy/pattern-matcher.js +185 -0
  48. package/dist/esm/naylence/fame/security/auth/policy/scope-matcher.js +162 -0
  49. package/dist/esm/naylence/fame/security/auth/policy-authorizer.js +1 -0
  50. package/dist/esm/naylence/fame/security/default-security-manager.js +94 -0
  51. package/dist/esm/naylence/fame/security/index.js +5 -1
  52. package/dist/esm/naylence/fame/security/node-security-profile-factory.js +14 -72
  53. package/dist/esm/naylence/fame/sentinel/router.js +64 -0
  54. package/dist/esm/naylence/fame/sentinel/sentinel.js +47 -3
  55. package/dist/esm/naylence/fame/util/register-runtime-factories.js +2 -0
  56. package/dist/esm/version.js +2 -2
  57. package/dist/node/index.cjs +3364 -1389
  58. package/dist/node/index.mjs +3324 -1387
  59. package/dist/node/node.cjs +3416 -1425
  60. package/dist/node/node.mjs +3376 -1423
  61. package/dist/types/naylence/fame/factory-manifest.d.ts +1 -1
  62. package/dist/types/naylence/fame/node/node-event-listener.d.ts +31 -0
  63. package/dist/types/naylence/fame/security/auth/authorization-profile-factory.d.ts +29 -0
  64. package/dist/types/naylence/fame/security/auth/authorizer.d.ts +37 -0
  65. package/dist/types/naylence/fame/security/auth/default-policy-authorizer-factory.d.ts +55 -0
  66. package/dist/types/naylence/fame/security/auth/default-policy-authorizer.d.ts +99 -0
  67. package/dist/types/naylence/fame/security/auth/oauth2-authorizer-factory.d.ts +2 -0
  68. package/dist/types/naylence/fame/security/auth/oauth2-authorizer.d.ts +2 -0
  69. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-definition.d.ts +166 -0
  70. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-factory.d.ts +38 -0
  71. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-source-factory.d.ts +38 -0
  72. package/dist/types/naylence/fame/security/auth/policy/authorization-policy-source.d.ts +20 -0
  73. package/dist/types/naylence/fame/security/auth/policy/authorization-policy.d.ts +55 -0
  74. package/dist/types/naylence/fame/security/auth/policy/basic-authorization-policy-factory.d.ts +42 -0
  75. package/dist/types/naylence/fame/security/auth/policy/basic-authorization-policy.d.ts +78 -0
  76. package/dist/types/naylence/fame/security/auth/policy/index.d.ts +19 -0
  77. package/dist/types/naylence/fame/security/auth/policy/local-file-authorization-policy-source-factory.d.ts +51 -0
  78. package/dist/types/naylence/fame/security/auth/policy/local-file-authorization-policy-source.d.ts +67 -0
  79. package/dist/types/naylence/fame/security/auth/policy/pattern-matcher.d.ts +84 -0
  80. package/dist/types/naylence/fame/security/auth/policy/scope-matcher.d.ts +61 -0
  81. package/dist/types/naylence/fame/security/auth/policy-authorizer.d.ts +12 -0
  82. package/dist/types/naylence/fame/security/default-security-manager.d.ts +22 -0
  83. package/dist/types/naylence/fame/security/index.d.ts +5 -1
  84. package/dist/types/naylence/fame/security/node-security-profile-factory.d.ts +2 -0
  85. package/dist/types/naylence/fame/sentinel/router.d.ts +68 -0
  86. package/dist/types/naylence/fame/sentinel/sentinel.d.ts +16 -0
  87. package/dist/types/version.d.ts +1 -1
  88. package/package.json +1 -1
@@ -63,8 +63,10 @@ exports.MODULES = [
63
63
  "./node/node-identity-policy-profile-factory.js",
64
64
  "./node/token-subject-node-identity-policy-factory.js",
65
65
  "./placement/static-node-placement-strategy-factory.js",
66
+ "./security/auth/authorization-profile-factory.js",
66
67
  "./security/auth/bearer-token-header-auth-injection-strategy-factory.js",
67
68
  "./security/auth/default-authorizer-factory.js",
69
+ "./security/auth/default-policy-authorizer-factory.js",
68
70
  "./security/auth/jwks-jwt-token-verifier-factory.js",
69
71
  "./security/auth/jwt-token-issuer-factory.js",
70
72
  "./security/auth/jwt-token-verifier-factory.js",
@@ -76,6 +78,8 @@ exports.MODULES = [
76
78
  "./security/auth/oauth2-authorizer-factory.js",
77
79
  "./security/auth/oauth2-client-credentials-token-provider-factory.js",
78
80
  "./security/auth/oauth2-pkce-token-provider-factory.js",
81
+ "./security/auth/policy/basic-authorization-policy-factory.js",
82
+ "./security/auth/policy/local-file-authorization-policy-source-factory.js",
79
83
  "./security/auth/query-param-auth-injection-strategy-factory.js",
80
84
  "./security/auth/shared-secret-authorizer-factory.js",
81
85
  "./security/auth/shared-secret-token-provider-factory.js",
@@ -142,8 +146,10 @@ exports.MODULE_LOADERS = {
142
146
  "./node/node-identity-policy-profile-factory.js": () => Promise.resolve().then(() => __importStar(require("./node/node-identity-policy-profile-factory.js"))),
143
147
  "./node/token-subject-node-identity-policy-factory.js": () => Promise.resolve().then(() => __importStar(require("./node/token-subject-node-identity-policy-factory.js"))),
144
148
  "./placement/static-node-placement-strategy-factory.js": () => Promise.resolve().then(() => __importStar(require("./placement/static-node-placement-strategy-factory.js"))),
149
+ "./security/auth/authorization-profile-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/authorization-profile-factory.js"))),
145
150
  "./security/auth/bearer-token-header-auth-injection-strategy-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/bearer-token-header-auth-injection-strategy-factory.js"))),
146
151
  "./security/auth/default-authorizer-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/default-authorizer-factory.js"))),
152
+ "./security/auth/default-policy-authorizer-factory.js": () => Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ /* @vite-ignore */ "./security/auth/default-policy-authorizer-factory.js"))),
147
153
  "./security/auth/jwks-jwt-token-verifier-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/jwks-jwt-token-verifier-factory.js"))),
148
154
  "./security/auth/jwt-token-issuer-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/jwt-token-issuer-factory.js"))),
149
155
  "./security/auth/jwt-token-verifier-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/jwt-token-verifier-factory.js"))),
@@ -155,6 +161,8 @@ exports.MODULE_LOADERS = {
155
161
  "./security/auth/oauth2-authorizer-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/oauth2-authorizer-factory.js"))),
156
162
  "./security/auth/oauth2-client-credentials-token-provider-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/oauth2-client-credentials-token-provider-factory.js"))),
157
163
  "./security/auth/oauth2-pkce-token-provider-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/oauth2-pkce-token-provider-factory.js"))),
164
+ "./security/auth/policy/basic-authorization-policy-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/policy/basic-authorization-policy-factory.js"))),
165
+ "./security/auth/policy/local-file-authorization-policy-source-factory.js": () => Promise.resolve().then(() => __importStar(require(/* webpackIgnore: true */ /* @vite-ignore */ "./security/auth/policy/local-file-authorization-policy-source-factory.js"))),
158
166
  "./security/auth/query-param-auth-injection-strategy-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/query-param-auth-injection-strategy-factory.js"))),
159
167
  "./security/auth/shared-secret-authorizer-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/shared-secret-authorizer-factory.js"))),
160
168
  "./security/auth/shared-secret-token-provider-factory.js": () => Promise.resolve().then(() => __importStar(require("./security/auth/shared-secret-token-provider-factory.js"))),
@@ -48,6 +48,10 @@ class BaseNodeEventListener {
48
48
  // Default implementation passes envelope through unchanged
49
49
  return envelope;
50
50
  }
51
+ async onRoutingActionSelected(_node, _envelope, selected, _state, _context) {
52
+ // Default implementation returns the selected action unchanged
53
+ return selected;
54
+ }
51
55
  async onForwardUpstream(_node, envelope, _context) {
52
56
  // Default implementation passes envelope through unchanged
53
57
  return envelope;
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AuthorizationProfileFactory = exports.FACTORY_META = exports.ENV_VAR_HMAC_SECRET = exports.ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE = exports.ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER = exports.ENV_VAR_TRUSTED_CLIENT_SCOPE = exports.ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY = exports.ENV_VAR_JWKS_URL = exports.ENV_VAR_JWT_AUDIENCE = exports.ENV_VAR_JWT_ALGORITHM = exports.ENV_VAR_JWT_TRUSTED_ISSUER = exports.PROFILE_NAME_NOOP = exports.PROFILE_NAME_OAUTH2_CALLBACK = exports.PROFILE_NAME_OAUTH2_GATED = exports.PROFILE_NAME_OAUTH2 = exports.PROFILE_NAME_DEFAULT = void 0;
4
+ const factory_1 = require("@naylence/factory");
5
+ const logging_js_1 = require("../../util/logging.js");
6
+ const authorizer_factory_js_1 = require("./authorizer-factory.js");
7
+ const logger = (0, logging_js_1.getLogger)('naylence.fame.security.auth.authorization_profile_factory');
8
+ exports.PROFILE_NAME_DEFAULT = 'jwt';
9
+ exports.PROFILE_NAME_OAUTH2 = 'oauth2';
10
+ exports.PROFILE_NAME_OAUTH2_GATED = 'oauth2-gated';
11
+ exports.PROFILE_NAME_OAUTH2_CALLBACK = 'oauth2-callback';
12
+ exports.PROFILE_NAME_NOOP = 'noop';
13
+ exports.ENV_VAR_JWT_TRUSTED_ISSUER = 'FAME_JWT_TRUSTED_ISSUER';
14
+ exports.ENV_VAR_JWT_ALGORITHM = 'FAME_JWT_ALGORITHM';
15
+ exports.ENV_VAR_JWT_AUDIENCE = 'FAME_JWT_AUDIENCE';
16
+ exports.ENV_VAR_JWKS_URL = 'FAME_JWKS_URL';
17
+ exports.ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY = 'FAME_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY';
18
+ exports.ENV_VAR_TRUSTED_CLIENT_SCOPE = 'FAME_TRUSTED_CLIENT_SCOPE';
19
+ exports.ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER = 'FAME_JWT_REVERSE_AUTH_TRUSTED_ISSUER';
20
+ exports.ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE = 'FAME_JWT_REVERSE_AUTH_AUDIENCE';
21
+ exports.ENV_VAR_HMAC_SECRET = 'FAME_HMAC_SECRET';
22
+ const DEFAULT_REVERSE_AUTH_ISSUER = 'reverse-auth.naylence.ai';
23
+ const DEFAULT_REVERSE_AUTH_AUDIENCE = 'dev.naylence.ai';
24
+ const DEFAULT_PROFILE = {
25
+ type: 'DefaultAuthorizer',
26
+ verifier: {
27
+ type: 'JWKSJWTTokenVerifier',
28
+ jwks_url: factory_1.Expressions.env(exports.ENV_VAR_JWKS_URL),
29
+ issuer: factory_1.Expressions.env(exports.ENV_VAR_JWT_TRUSTED_ISSUER),
30
+ },
31
+ };
32
+ const OAUTH2_PROFILE = {
33
+ type: 'OAuth2Authorizer',
34
+ issuer: factory_1.Expressions.env(exports.ENV_VAR_JWT_TRUSTED_ISSUER),
35
+ required_scopes: ['node.connect'],
36
+ require_scope: true,
37
+ default_ttl_sec: 3600,
38
+ max_ttl_sec: 86400,
39
+ algorithm: factory_1.Expressions.env(exports.ENV_VAR_JWT_ALGORITHM, 'RS256'),
40
+ audience: factory_1.Expressions.env(exports.ENV_VAR_JWT_AUDIENCE),
41
+ };
42
+ const OAUTH2_GATED_PROFILE = {
43
+ ...OAUTH2_PROFILE,
44
+ enforce_token_subject_node_identity: factory_1.Expressions.env(exports.ENV_VAR_ENFORCE_TOKEN_SUBJECT_NODE_IDENTITY, 'false'),
45
+ trusted_client_scope: factory_1.Expressions.env(exports.ENV_VAR_TRUSTED_CLIENT_SCOPE, 'node.trusted'),
46
+ };
47
+ const OAUTH2_CALLBACK_PROFILE = {
48
+ type: 'OAuth2Authorizer',
49
+ issuer: factory_1.Expressions.env(exports.ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER, DEFAULT_REVERSE_AUTH_ISSUER),
50
+ audience: factory_1.Expressions.env(exports.ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE),
51
+ require_scope: true,
52
+ default_ttl_sec: 3600,
53
+ max_ttl_sec: 86400,
54
+ reverse_auth_ttl_sec: 86400,
55
+ token_verifier_config: {
56
+ type: 'JWTTokenVerifier',
57
+ algorithm: 'HS256',
58
+ hmac_secret: factory_1.Expressions.env(exports.ENV_VAR_HMAC_SECRET),
59
+ issuer: factory_1.Expressions.env(exports.ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER, DEFAULT_REVERSE_AUTH_ISSUER),
60
+ ttl_sec: 86400,
61
+ },
62
+ token_issuer_config: {
63
+ type: 'JWTTokenIssuer',
64
+ algorithm: 'HS256',
65
+ hmac_secret: factory_1.Expressions.env(exports.ENV_VAR_HMAC_SECRET),
66
+ kid: 'hmac-reverse-auth-key',
67
+ issuer: factory_1.Expressions.env(exports.ENV_VAR_JWT_REVERSE_AUTH_TRUSTED_ISSUER, DEFAULT_REVERSE_AUTH_ISSUER),
68
+ ttl_sec: 86400,
69
+ audience: factory_1.Expressions.env(exports.ENV_VAR_JWT_REVERSE_AUTH_AUDIENCE, DEFAULT_REVERSE_AUTH_AUDIENCE),
70
+ },
71
+ };
72
+ const NOOP_PROFILE = {
73
+ type: 'NoopAuthorizer',
74
+ };
75
+ const PROFILE_MAP = {
76
+ [exports.PROFILE_NAME_DEFAULT]: DEFAULT_PROFILE,
77
+ [exports.PROFILE_NAME_OAUTH2]: OAUTH2_PROFILE,
78
+ [exports.PROFILE_NAME_OAUTH2_GATED]: OAUTH2_GATED_PROFILE,
79
+ [exports.PROFILE_NAME_OAUTH2_CALLBACK]: OAUTH2_CALLBACK_PROFILE,
80
+ [exports.PROFILE_NAME_NOOP]: NOOP_PROFILE,
81
+ };
82
+ const PROFILE_ALIASES = {
83
+ jwt: exports.PROFILE_NAME_DEFAULT,
84
+ jwks: exports.PROFILE_NAME_DEFAULT,
85
+ default: exports.PROFILE_NAME_DEFAULT,
86
+ oauth2: exports.PROFILE_NAME_OAUTH2,
87
+ oidc: exports.PROFILE_NAME_OAUTH2,
88
+ 'oauth2-gated': exports.PROFILE_NAME_OAUTH2_GATED,
89
+ oauth2_gated: exports.PROFILE_NAME_OAUTH2_GATED,
90
+ 'oauth2-callback': exports.PROFILE_NAME_OAUTH2_CALLBACK,
91
+ oauth2_callback: exports.PROFILE_NAME_OAUTH2_CALLBACK,
92
+ 'reverse-auth': exports.PROFILE_NAME_OAUTH2_CALLBACK,
93
+ noop: exports.PROFILE_NAME_NOOP,
94
+ 'no-op': exports.PROFILE_NAME_NOOP,
95
+ no_op: exports.PROFILE_NAME_NOOP,
96
+ };
97
+ exports.FACTORY_META = {
98
+ base: authorizer_factory_js_1.AUTHORIZER_FACTORY_BASE_TYPE,
99
+ key: 'AuthorizationProfile',
100
+ };
101
+ class AuthorizationProfileFactory extends authorizer_factory_js_1.AuthorizerFactory {
102
+ constructor() {
103
+ super(...arguments);
104
+ this.type = 'AuthorizationProfile';
105
+ }
106
+ async create(config, ...factoryArgs) {
107
+ const normalized = normalizeConfig(config);
108
+ const profileConfig = resolveProfileConfig(normalized.profile);
109
+ logger.debug('enabling_authorization_profile', {
110
+ profile: normalized.profile,
111
+ });
112
+ const authorizer = await authorizer_factory_js_1.AuthorizerFactory.createAuthorizer(profileConfig, { factoryArgs });
113
+ if (!authorizer) {
114
+ throw new Error(`Failed to create authorizer for profile: ${normalized.profile}`);
115
+ }
116
+ return authorizer;
117
+ }
118
+ }
119
+ exports.AuthorizationProfileFactory = AuthorizationProfileFactory;
120
+ function normalizeConfig(config) {
121
+ if (!config) {
122
+ return { profile: exports.PROFILE_NAME_OAUTH2 };
123
+ }
124
+ const candidate = config;
125
+ const profileValue = resolveProfileName(candidate);
126
+ const canonicalProfile = canonicalizeProfileName(profileValue);
127
+ candidate.profile = canonicalProfile;
128
+ return { profile: canonicalProfile };
129
+ }
130
+ function resolveProfileName(candidate) {
131
+ const direct = coerceProfileString(candidate.profile);
132
+ if (direct) {
133
+ return direct;
134
+ }
135
+ const legacyKeys = ['profile_name', 'profileName'];
136
+ for (const legacyKey of legacyKeys) {
137
+ const legacyValue = coerceProfileString(candidate[legacyKey]);
138
+ if (legacyValue) {
139
+ return legacyValue;
140
+ }
141
+ }
142
+ return exports.PROFILE_NAME_OAUTH2;
143
+ }
144
+ function coerceProfileString(value) {
145
+ if (typeof value !== 'string') {
146
+ return null;
147
+ }
148
+ const trimmed = value.trim();
149
+ return trimmed.length > 0 ? trimmed : null;
150
+ }
151
+ function canonicalizeProfileName(value) {
152
+ const normalized = value.replace(/[\s_]+/g, '-').toLowerCase();
153
+ return PROFILE_ALIASES[normalized] ?? normalized;
154
+ }
155
+ function resolveProfileConfig(profileName) {
156
+ const profile = PROFILE_MAP[profileName];
157
+ if (!profile) {
158
+ throw new Error(`Unknown authorization profile: ${profileName}`);
159
+ }
160
+ return deepClone(profile);
161
+ }
162
+ function deepClone(value) {
163
+ return JSON.parse(JSON.stringify(value));
164
+ }
165
+ exports.default = AuthorizationProfileFactory;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DefaultPolicyAuthorizerFactory = exports.FACTORY_META = void 0;
37
+ const lazy_import_js_1 = require("../../util/lazy-import.js");
38
+ const authorizer_factory_js_1 = require("./authorizer-factory.js");
39
+ const token_verifier_factory_js_1 = require("./token-verifier-factory.js");
40
+ const authorization_policy_source_factory_js_1 = require("./policy/authorization-policy-source-factory.js");
41
+ const authorization_policy_factory_js_1 = require("./policy/authorization-policy-factory.js");
42
+ let defaultPolicyAuthorizerModulePromise = null;
43
+ async function getDefaultPolicyAuthorizerModule() {
44
+ if (!defaultPolicyAuthorizerModulePromise) {
45
+ defaultPolicyAuthorizerModulePromise = (0, lazy_import_js_1.safeImport)(() => Promise.resolve().then(() => __importStar(require('./default-policy-authorizer.js'))), 'default-policy-authorizer');
46
+ }
47
+ return defaultPolicyAuthorizerModulePromise;
48
+ }
49
+ function normalizeConfig(config) {
50
+ if (!config) {
51
+ return {};
52
+ }
53
+ const candidate = config;
54
+ const verifierConfig = candidate.verifier ?? null;
55
+ if (verifierConfig && typeof verifierConfig !== 'object') {
56
+ throw new Error('PolicyAuthorizer verifier configuration must be an object');
57
+ }
58
+ const policyConfig = candidate.policy ?? null;
59
+ if (policyConfig && typeof policyConfig !== 'object') {
60
+ throw new Error('PolicyAuthorizer policy configuration must be an object');
61
+ }
62
+ const policySourceConfig = candidate.policySource ?? candidate.policy_source ?? null;
63
+ if (policySourceConfig && typeof policySourceConfig !== 'object') {
64
+ throw new Error('PolicyAuthorizer policySource configuration must be an object');
65
+ }
66
+ return {
67
+ verifier: verifierConfig,
68
+ policy: policyConfig,
69
+ policySource: policySourceConfig,
70
+ };
71
+ }
72
+ function isTokenVerifier(candidate) {
73
+ return Boolean(candidate && typeof candidate.verify === 'function');
74
+ }
75
+ function isAuthorizationPolicy(candidate) {
76
+ return Boolean(candidate &&
77
+ typeof candidate.evaluateRequest === 'function');
78
+ }
79
+ function isAuthorizationPolicySource(candidate) {
80
+ return Boolean(candidate &&
81
+ typeof candidate.loadPolicy === 'function');
82
+ }
83
+ /**
84
+ * Factory metadata for registration.
85
+ */
86
+ exports.FACTORY_META = {
87
+ base: authorizer_factory_js_1.AUTHORIZER_FACTORY_BASE_TYPE,
88
+ key: 'PolicyAuthorizer',
89
+ };
90
+ /**
91
+ * Factory for creating DefaultPolicyAuthorizer instances.
92
+ *
93
+ * This factory uses lazy loading to avoid pulling in Node.js-specific
94
+ * code in browser environments.
95
+ */
96
+ class DefaultPolicyAuthorizerFactory extends authorizer_factory_js_1.AuthorizerFactory {
97
+ constructor() {
98
+ super(...arguments);
99
+ this.type = 'PolicyAuthorizer';
100
+ this.isDefault = true;
101
+ }
102
+ /**
103
+ * Creates a DefaultPolicyAuthorizer from the given configuration.
104
+ *
105
+ * @param config - Configuration for the authorizer
106
+ * @param factoryArgs - Additional factory arguments:
107
+ * - TokenVerifier instance
108
+ * - AuthorizationPolicy instance
109
+ * - AuthorizationPolicySource instance
110
+ * @returns The created authorizer
111
+ */
112
+ async create(config, ...factoryArgs) {
113
+ const normalized = normalizeConfig(config);
114
+ // Resolve token verifier
115
+ let tokenVerifier = factoryArgs.find(isTokenVerifier);
116
+ if (!tokenVerifier && normalized.verifier) {
117
+ tokenVerifier = await token_verifier_factory_js_1.TokenVerifierFactory.createTokenVerifier(normalized.verifier);
118
+ }
119
+ if (!tokenVerifier) {
120
+ throw new Error('PolicyAuthorizer requires a verifier configuration or instance');
121
+ }
122
+ // Resolve policy or policy source
123
+ let policy = factoryArgs.find(isAuthorizationPolicy);
124
+ let policySource = factoryArgs.find(isAuthorizationPolicySource);
125
+ // Create policy from config if not provided as argument
126
+ if (!policy && normalized.policy) {
127
+ policy = await authorization_policy_factory_js_1.AuthorizationPolicyFactory.createAuthorizationPolicy(normalized.policy);
128
+ }
129
+ // Create policy source from config if not provided as argument
130
+ if (!policySource && normalized.policySource) {
131
+ policySource =
132
+ await authorization_policy_source_factory_js_1.AuthorizationPolicySourceFactory.createAuthorizationPolicySource(normalized.policySource);
133
+ }
134
+ // Validate that we have either policy or policy source
135
+ if (!policy && !policySource) {
136
+ throw new Error('PolicyAuthorizer requires either a policy or policySource configuration');
137
+ }
138
+ const { DefaultPolicyAuthorizer } = await getDefaultPolicyAuthorizerModule();
139
+ return new DefaultPolicyAuthorizer({
140
+ tokenVerifier,
141
+ policy,
142
+ policySource,
143
+ });
144
+ }
145
+ }
146
+ exports.DefaultPolicyAuthorizerFactory = DefaultPolicyAuthorizerFactory;
147
+ exports.default = DefaultPolicyAuthorizerFactory;
@@ -0,0 +1,291 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DefaultPolicyAuthorizer = void 0;
4
+ const core_1 = require("@naylence/core");
5
+ const logging_js_1 = require("../../util/logging.js");
6
+ const logger = (0, logging_js_1.getLogger)('naylence.fame.security.auth.default_policy_authorizer');
7
+ function decodeCredentials(credentials) {
8
+ if (typeof TextDecoder !== 'undefined') {
9
+ return new TextDecoder().decode(credentials);
10
+ }
11
+ if (typeof Buffer !== 'undefined') {
12
+ return Buffer.from(credentials).toString('utf-8');
13
+ }
14
+ throw new Error('Unable to decode credential bytes without TextDecoder support');
15
+ }
16
+ function normalizeToken(credentials) {
17
+ const raw = typeof credentials === 'string'
18
+ ? credentials
19
+ : decodeCredentials(credentials);
20
+ const trimmed = raw.trim();
21
+ if (trimmed.length === 0) {
22
+ return undefined;
23
+ }
24
+ if (trimmed.toLowerCase().startsWith('bearer ')) {
25
+ const candidate = trimmed.slice(7).trim();
26
+ return candidate.length > 0 ? candidate : undefined;
27
+ }
28
+ return trimmed;
29
+ }
30
+ function normalizeOptions(options) {
31
+ if (options === undefined || options === null) {
32
+ return {};
33
+ }
34
+ if (typeof options !== 'object') {
35
+ throw new TypeError('DefaultPolicyAuthorizer options must be an object');
36
+ }
37
+ const candidate = options;
38
+ return {
39
+ tokenVerifier: candidate.tokenVerifier ?? candidate.token_verifier,
40
+ policy: candidate.policy,
41
+ policySource: candidate.policySource ?? candidate.policy_source,
42
+ };
43
+ }
44
+ /**
45
+ * An authorizer that delegates authorization decisions to a pluggable policy.
46
+ *
47
+ * This authorizer combines token-based authentication with policy-based
48
+ * authorization. The token verifier handles authentication (validating
49
+ * credentials), while the authorization policy handles authorization
50
+ * decisions (allow/deny based on the request context).
51
+ */
52
+ class DefaultPolicyAuthorizer {
53
+ constructor(options = {}) {
54
+ this.policyLoaded = false;
55
+ const normalized = normalizeOptions(options);
56
+ if (normalized.tokenVerifier) {
57
+ this.tokenVerifierImpl = normalized.tokenVerifier;
58
+ }
59
+ if (normalized.policy) {
60
+ this.policyImpl = normalized.policy;
61
+ this.policyLoaded = true;
62
+ }
63
+ if (normalized.policySource) {
64
+ this.policySource = normalized.policySource;
65
+ }
66
+ // Validate that we have either a policy or a policy source
67
+ if (!normalized.policy && !normalized.policySource) {
68
+ throw new Error('DefaultPolicyAuthorizer requires either a policy or a policySource');
69
+ }
70
+ }
71
+ /**
72
+ * The currently active authorization policy.
73
+ */
74
+ get policy() {
75
+ if (!this.policyImpl) {
76
+ throw new Error('Authorization policy not loaded. Call ensurePolicyLoaded() first.');
77
+ }
78
+ return this.policyImpl;
79
+ }
80
+ /**
81
+ * The token verifier used for authentication.
82
+ */
83
+ get tokenVerifier() {
84
+ if (!this.tokenVerifierImpl) {
85
+ throw new Error('DefaultPolicyAuthorizer is not initialized properly, missing tokenVerifier');
86
+ }
87
+ return this.tokenVerifierImpl;
88
+ }
89
+ set tokenVerifier(verifier) {
90
+ this.tokenVerifierImpl = verifier;
91
+ }
92
+ /**
93
+ * Ensures the authorization policy is loaded.
94
+ * If using a policy source, loads the policy from it.
95
+ */
96
+ async ensurePolicyLoaded() {
97
+ if (this.policyLoaded && this.policyImpl) {
98
+ return;
99
+ }
100
+ if (!this.policySource) {
101
+ throw new Error('No policy source configured and no policy provided');
102
+ }
103
+ logger.debug('loading_policy_from_source');
104
+ this.policyImpl = await this.policySource.loadPolicy();
105
+ this.policyLoaded = true;
106
+ logger.info('policy_loaded_from_source');
107
+ }
108
+ /**
109
+ * Reloads the authorization policy from the policy source.
110
+ * Only works if a policy source was configured.
111
+ */
112
+ async reloadPolicy() {
113
+ if (!this.policySource) {
114
+ throw new Error('Cannot reload policy: no policy source configured');
115
+ }
116
+ logger.debug('reloading_policy_from_source');
117
+ this.policyImpl = await this.policySource.loadPolicy();
118
+ this.policyLoaded = true;
119
+ logger.info('policy_reloaded_from_source');
120
+ }
121
+ /**
122
+ * Authenticates credentials and returns an authorization context.
123
+ *
124
+ * @param credentials - The credentials to authenticate (token string or bytes)
125
+ * @returns The authorization context if authentication succeeds, undefined otherwise
126
+ */
127
+ async authenticate(credentials) {
128
+ const token = normalizeToken(credentials);
129
+ if (!token) {
130
+ return undefined;
131
+ }
132
+ try {
133
+ const verifier = this.tokenVerifier;
134
+ const context = await verifier.verify(token);
135
+ return (0, core_1.createAuthorizationContext)({
136
+ ...context,
137
+ authenticated: true,
138
+ authorized: false, // Authorization happens in authorize()
139
+ authMethod: context.authMethod ?? 'jwt',
140
+ });
141
+ }
142
+ catch (error) {
143
+ logger.warning('token_verification_failed', {
144
+ error: error instanceof Error ? error.message : String(error),
145
+ });
146
+ return undefined;
147
+ }
148
+ }
149
+ /**
150
+ * Authorizes a request using the configured authorization policy.
151
+ *
152
+ * For NodeAttach frames, evaluates policy with action='Connect'.
153
+ * For other frames, this method performs basic authentication validation
154
+ * but does NOT infer send/receive actions. Route-level authorization
155
+ * is handled separately via authorizeRoute().
156
+ *
157
+ * @param node - The node handling the request
158
+ * @param envelope - The FAME envelope being authorized
159
+ * @param context - Optional delivery context
160
+ * @returns The authorization context if authorized, undefined if denied
161
+ */
162
+ async authorize(node, envelope, context) {
163
+ const authorization = context?.security?.authorization;
164
+ // Must be authenticated first
165
+ if (!authorization || !authorization.authenticated) {
166
+ logger.debug('authorization_denied_not_authenticated');
167
+ return undefined;
168
+ }
169
+ // Ensure policy is loaded
170
+ await this.ensurePolicyLoaded();
171
+ // For NodeAttach frames, evaluate policy with 'Connect' action
172
+ const frameType = envelope.frame?.type;
173
+ if (frameType === 'NodeAttach') {
174
+ let decision;
175
+ try {
176
+ decision = await this.policy.evaluateRequest(node, envelope, context, 'Connect');
177
+ }
178
+ catch (error) {
179
+ logger.error('policy_evaluation_failed', {
180
+ error: error instanceof Error ? error.message : String(error),
181
+ action: 'Connect',
182
+ });
183
+ return undefined;
184
+ }
185
+ if (decision.effect === 'allow') {
186
+ logger.debug('authorization_allowed', {
187
+ matchedRule: decision.matchedRule,
188
+ reason: decision.reason,
189
+ action: 'Connect',
190
+ });
191
+ return (0, core_1.createAuthorizationContext)({
192
+ ...authorization,
193
+ authorized: true,
194
+ authMethod: authorization.authMethod ?? 'policy',
195
+ });
196
+ }
197
+ else {
198
+ logger.debug('authorization_denied', {
199
+ matchedRule: decision.matchedRule,
200
+ reason: decision.reason,
201
+ action: 'Connect',
202
+ });
203
+ return undefined;
204
+ }
205
+ }
206
+ // For non-NodeAttach frames, authentication is sufficient at this stage.
207
+ // Route-level authorization is performed via authorizeRoute() after
208
+ // the routing decision is made.
209
+ logger.debug('authorization_passed_authentication_only', {
210
+ envp_id: envelope.id,
211
+ frame_type: frameType,
212
+ });
213
+ return (0, core_1.createAuthorizationContext)({
214
+ ...authorization,
215
+ authorized: true,
216
+ authMethod: authorization.authMethod ?? 'policy',
217
+ });
218
+ }
219
+ /**
220
+ * Authorizes a routing action after the routing decision has been made.
221
+ *
222
+ * This method evaluates the authorization policy with the explicitly
223
+ * provided action token (ForwardUpstream, ForwardDownstream, ForwardPeer,
224
+ * DeliverLocal).
225
+ *
226
+ * @param node - The node handling the request
227
+ * @param envelope - The FAME envelope being routed
228
+ * @param action - The authorization action token from the routing decision
229
+ * @param context - Optional delivery context
230
+ * @returns RouteAuthorizationResult with authorization decision
231
+ */
232
+ async authorizeRoute(node, envelope, action, context) {
233
+ const authorization = context?.security?.authorization;
234
+ // If not authenticated, deny route authorization
235
+ if (!authorization || !authorization.authenticated) {
236
+ logger.debug('route_authorization_denied_not_authenticated', {
237
+ action,
238
+ });
239
+ return {
240
+ authorized: false,
241
+ denialReason: 'not_authenticated',
242
+ };
243
+ }
244
+ // Ensure policy is loaded
245
+ await this.ensurePolicyLoaded();
246
+ // Evaluate the policy with the provided action
247
+ let decision;
248
+ try {
249
+ decision = await this.policy.evaluateRequest(node, envelope, context, action);
250
+ }
251
+ catch (error) {
252
+ logger.error('route_policy_evaluation_failed', {
253
+ error: error instanceof Error ? error.message : String(error),
254
+ action,
255
+ });
256
+ return {
257
+ authorized: false,
258
+ denialReason: 'policy_evaluation_error',
259
+ };
260
+ }
261
+ if (decision.effect === 'allow') {
262
+ logger.debug('route_authorization_allowed', {
263
+ matchedRule: decision.matchedRule,
264
+ reason: decision.reason,
265
+ action,
266
+ });
267
+ return {
268
+ authorized: true,
269
+ authContext: (0, core_1.createAuthorizationContext)({
270
+ ...authorization,
271
+ authorized: true,
272
+ authMethod: authorization.authMethod ?? 'policy',
273
+ }),
274
+ matchedRule: decision.matchedRule,
275
+ };
276
+ }
277
+ else {
278
+ logger.debug('route_authorization_denied', {
279
+ matchedRule: decision.matchedRule,
280
+ reason: decision.reason,
281
+ action,
282
+ });
283
+ return {
284
+ authorized: false,
285
+ denialReason: decision.reason ?? 'policy_denied',
286
+ matchedRule: decision.matchedRule,
287
+ };
288
+ }
289
+ }
290
+ }
291
+ exports.DefaultPolicyAuthorizer = DefaultPolicyAuthorizer;