@naylence/advanced-security 0.4.4 → 0.4.6

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 (85) hide show
  1. package/dist/browser/index.cjs +702 -32
  2. package/dist/browser/index.mjs +702 -32
  3. package/dist/cjs/advanced-security-isomorphic.js +1 -1
  4. package/dist/cjs/advanced-security-isomorphic.js.map +1 -1
  5. package/dist/cjs/naylence/fame/expr/builtins.js +1 -1
  6. package/dist/cjs/naylence/fame/expr/builtins.js.map +1 -1
  7. package/dist/cjs/naylence/fame/factory-manifest.js +2 -0
  8. package/dist/cjs/naylence/fame/factory-manifest.js.map +1 -1
  9. package/dist/cjs/naylence/fame/security/auth/index.js +2 -0
  10. package/dist/cjs/naylence/fame/security/auth/index.js.map +1 -1
  11. package/dist/cjs/naylence/fame/security/auth/policy/advanced-authorization-policy.js +32 -13
  12. package/dist/cjs/naylence/fame/security/auth/policy/advanced-authorization-policy.js.map +1 -1
  13. package/dist/cjs/naylence/fame/security/auth/policy/auth-policy-server-cli.js +47 -0
  14. package/dist/cjs/naylence/fame/security/auth/policy/auth-policy-server-cli.js.map +1 -0
  15. package/dist/cjs/naylence/fame/security/auth/policy/auth-policy-server.js +553 -0
  16. package/dist/cjs/naylence/fame/security/auth/policy/auth-policy-server.js.map +1 -0
  17. package/dist/cjs/naylence/fame/security/auth/policy/expr-builtins.js +166 -2
  18. package/dist/cjs/naylence/fame/security/auth/policy/expr-builtins.js.map +1 -1
  19. package/dist/cjs/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.js +108 -0
  20. package/dist/cjs/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.js.map +1 -0
  21. package/dist/cjs/naylence/fame/security/auth/policy/http-authorization-policy-source.js +367 -0
  22. package/dist/cjs/naylence/fame/security/auth/policy/http-authorization-policy-source.js.map +1 -0
  23. package/dist/cjs/naylence/fame/security/auth/policy/index.js +4 -2
  24. package/dist/cjs/naylence/fame/security/auth/policy/index.js.map +1 -1
  25. package/dist/cjs/naylence/fame/security/auth/policy-http-authorization-profile.js +78 -0
  26. package/dist/cjs/naylence/fame/security/auth/policy-http-authorization-profile.js.map +1 -0
  27. package/dist/cjs/naylence/fame/security/register-advanced-security-factories.js +2 -0
  28. package/dist/cjs/naylence/fame/security/register-advanced-security-factories.js.map +1 -1
  29. package/dist/cjs/version.js +2 -2
  30. package/dist/esm/advanced-security-isomorphic.js +1 -1
  31. package/dist/esm/advanced-security-isomorphic.js.map +1 -1
  32. package/dist/esm/naylence/fame/expr/builtins.js +1 -1
  33. package/dist/esm/naylence/fame/expr/builtins.js.map +1 -1
  34. package/dist/esm/naylence/fame/factory-manifest.js +2 -0
  35. package/dist/esm/naylence/fame/factory-manifest.js.map +1 -1
  36. package/dist/esm/naylence/fame/security/auth/index.js +2 -0
  37. package/dist/esm/naylence/fame/security/auth/index.js.map +1 -1
  38. package/dist/esm/naylence/fame/security/auth/policy/advanced-authorization-policy.js +32 -13
  39. package/dist/esm/naylence/fame/security/auth/policy/advanced-authorization-policy.js.map +1 -1
  40. package/dist/esm/naylence/fame/security/auth/policy/auth-policy-server-cli.js +47 -0
  41. package/dist/esm/naylence/fame/security/auth/policy/auth-policy-server-cli.js.map +1 -0
  42. package/dist/esm/naylence/fame/security/auth/policy/auth-policy-server.js +553 -0
  43. package/dist/esm/naylence/fame/security/auth/policy/auth-policy-server.js.map +1 -0
  44. package/dist/esm/naylence/fame/security/auth/policy/expr-builtins.js +166 -2
  45. package/dist/esm/naylence/fame/security/auth/policy/expr-builtins.js.map +1 -1
  46. package/dist/esm/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.js +108 -0
  47. package/dist/esm/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.js.map +1 -0
  48. package/dist/esm/naylence/fame/security/auth/policy/http-authorization-policy-source.js +367 -0
  49. package/dist/esm/naylence/fame/security/auth/policy/http-authorization-policy-source.js.map +1 -0
  50. package/dist/esm/naylence/fame/security/auth/policy/index.js +4 -2
  51. package/dist/esm/naylence/fame/security/auth/policy/index.js.map +1 -1
  52. package/dist/esm/naylence/fame/security/auth/policy-http-authorization-profile.js +78 -0
  53. package/dist/esm/naylence/fame/security/auth/policy-http-authorization-profile.js.map +1 -0
  54. package/dist/esm/naylence/fame/security/register-advanced-security-factories.js +2 -0
  55. package/dist/esm/naylence/fame/security/register-advanced-security-factories.js.map +1 -1
  56. package/dist/esm/version.js +2 -2
  57. package/dist/node/index.cjs +777 -139
  58. package/dist/node/index.mjs +770 -109
  59. package/dist/node/node.cjs +788 -65
  60. package/dist/node/node.mjs +780 -34
  61. package/dist/types/advanced-security-isomorphic.d.ts +0 -1
  62. package/dist/types/advanced-security-isomorphic.d.ts.map +1 -1
  63. package/dist/types/naylence/fame/factory-manifest.d.ts +1 -1
  64. package/dist/types/naylence/fame/factory-manifest.d.ts.map +1 -1
  65. package/dist/types/naylence/fame/security/auth/index.d.ts +1 -0
  66. package/dist/types/naylence/fame/security/auth/index.d.ts.map +1 -1
  67. package/dist/types/naylence/fame/security/auth/policy/advanced-authorization-policy.d.ts.map +1 -1
  68. package/dist/types/naylence/fame/security/auth/policy/auth-policy-server-cli.d.ts +20 -0
  69. package/dist/types/naylence/fame/security/auth/policy/auth-policy-server-cli.d.ts.map +1 -0
  70. package/dist/types/naylence/fame/security/auth/policy/auth-policy-server.d.ts +74 -0
  71. package/dist/types/naylence/fame/security/auth/policy/auth-policy-server.d.ts.map +1 -0
  72. package/dist/types/naylence/fame/security/auth/policy/expr-builtins.d.ts +71 -1
  73. package/dist/types/naylence/fame/security/auth/policy/expr-builtins.d.ts.map +1 -1
  74. package/dist/types/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.d.ts +81 -0
  75. package/dist/types/naylence/fame/security/auth/policy/http-authorization-policy-source-factory.d.ts.map +1 -0
  76. package/dist/types/naylence/fame/security/auth/policy/http-authorization-policy-source.d.ts +150 -0
  77. package/dist/types/naylence/fame/security/auth/policy/http-authorization-policy-source.d.ts.map +1 -0
  78. package/dist/types/naylence/fame/security/auth/policy/index.d.ts +2 -1
  79. package/dist/types/naylence/fame/security/auth/policy/index.d.ts.map +1 -1
  80. package/dist/types/naylence/fame/security/auth/policy-http-authorization-profile.d.ts +17 -0
  81. package/dist/types/naylence/fame/security/auth/policy-http-authorization-profile.d.ts.map +1 -0
  82. package/dist/types/naylence/fame/security/register-advanced-security-factories.d.ts +1 -0
  83. package/dist/types/naylence/fame/security/register-advanced-security-factories.d.ts.map +1 -1
  84. package/dist/types/version.d.ts +1 -1
  85. package/package.json +3 -2
@@ -2,8 +2,9 @@
2
2
 
3
3
  var factory = require('@naylence/factory');
4
4
  var runtime = require('@naylence/runtime');
5
- var sha256 = require('@noble/hashes/sha256');
5
+ var sha2 = require('@noble/hashes/sha2');
6
6
  var core = require('@naylence/core');
7
+ var yaml = require('yaml');
7
8
  var asn1Schema = require('@peculiar/asn1-schema');
8
9
  var asn1X509 = require('@peculiar/asn1-x509');
9
10
  var sha2_js = require('@noble/hashes/sha2.js');
@@ -25,6 +26,7 @@ var sha256_js = require('@noble/hashes/sha256.js');
25
26
  */
26
27
  const MODULES = [
27
28
  "./security/auth/policy/advanced-authorization-policy-factory.js",
29
+ "./security/auth/policy/http-authorization-policy-source-factory.js",
28
30
  "./security/cert/default-ca-service-factory.js",
29
31
  "./security/cert/default-certificate-manager-factory.js",
30
32
  "./security/cert/trust-store/browser-trust-store-provider-factory.js",
@@ -42,6 +44,7 @@ const MODULES = [
42
44
  ];
43
45
  const MODULE_LOADERS = {
44
46
  "./security/auth/policy/advanced-authorization-policy-factory.js": () => Promise.resolve().then(function () { return advancedAuthorizationPolicyFactory; }),
47
+ "./security/auth/policy/http-authorization-policy-source-factory.js": () => Promise.resolve().then(function () { return httpAuthorizationPolicySourceFactory; }),
45
48
  "./security/cert/default-ca-service-factory.js": () => Promise.resolve().then(function () { return defaultCaServiceFactory; }),
46
49
  "./security/cert/default-certificate-manager-factory.js": () => Promise.resolve().then(function () { return defaultCertificateManagerFactory; }),
47
50
  "./security/cert/trust-store/browser-trust-store-provider-factory.js": () => Promise.resolve().then(function () { return browserTrustStoreProviderFactory; }),
@@ -58,7 +61,7 @@ const MODULE_LOADERS = {
58
61
  "./welcome/advanced-welcome-service-factory.js": () => Promise.resolve().then(function () { return advancedWelcomeServiceFactory; }),
59
62
  };
60
63
 
61
- const logger$h = runtime.getLogger("naylence.fame.security.encryption.encryption_manager_registry");
64
+ const logger$i = runtime.getLogger("naylence.fame.security.encryption.encryption_manager_registry");
62
65
  class EncryptionManagerFactoryRegistry {
63
66
  constructor(autoDiscover = true) {
64
67
  this.factories = [];
@@ -80,7 +83,7 @@ class EncryptionManagerFactoryRegistry {
80
83
  let registeredCount = 0;
81
84
  for (const [factoryName, info] of extensionInfos) {
82
85
  if (factoryName === "CompositeEncryptionManager") {
83
- logger$h.debug("skipping_composite_factory_to_avoid_circular_dependency", {
86
+ logger$i.debug("skipping_composite_factory_to_avoid_circular_dependency", {
84
87
  factory_name: factoryName,
85
88
  });
86
89
  continue;
@@ -90,7 +93,7 @@ class EncryptionManagerFactoryRegistry {
90
93
  factory.ExtensionManager.getGlobalFactory(runtime.ENCRYPTION_MANAGER_FACTORY_BASE_TYPE, factoryName));
91
94
  this.registerFactory(factoryInstance, { autoDiscovered: true });
92
95
  registeredCount += 1;
93
- logger$h.debug("auto_discovered_factory", {
96
+ logger$i.debug("auto_discovered_factory", {
94
97
  factory_name: factoryName,
95
98
  factory_class: factoryInstance.constructor.name,
96
99
  algorithms: factoryInstance.getSupportedAlgorithms(),
@@ -99,21 +102,21 @@ class EncryptionManagerFactoryRegistry {
99
102
  });
100
103
  }
101
104
  catch (error) {
102
- logger$h.warning("failed_to_auto_register_factory", {
105
+ logger$i.warning("failed_to_auto_register_factory", {
103
106
  factory_name: factoryName,
104
107
  error: error instanceof Error ? error.message : String(error),
105
108
  });
106
109
  }
107
110
  }
108
111
  this.autoDiscovered = true;
109
- logger$h.debug("completed_auto_discovery", {
112
+ logger$i.debug("completed_auto_discovery", {
110
113
  registered_factories: registeredCount,
111
114
  total_discovered: extensionInfos.size,
112
115
  skipped_composite: true,
113
116
  });
114
117
  }
115
118
  catch (error) {
116
- logger$h.warning("failed_auto_discovery_of_factories", {
119
+ logger$i.warning("failed_auto_discovery_of_factories", {
117
120
  error: error instanceof Error ? error.message : String(error),
118
121
  });
119
122
  }
@@ -131,7 +134,7 @@ class EncryptionManagerFactoryRegistry {
131
134
  const existing = this.algorithmToFactory.get(algorithm);
132
135
  if (!existing || factory.getPriority() > existing.getPriority()) {
133
136
  this.algorithmToFactory.set(algorithm, factory);
134
- logger$h.debug("registered_algorithm_mapping", {
137
+ logger$i.debug("registered_algorithm_mapping", {
135
138
  algorithm,
136
139
  factory: factory.constructor.name,
137
140
  priority: factory.getPriority(),
@@ -143,7 +146,7 @@ class EncryptionManagerFactoryRegistry {
143
146
  typeFactories.push(factory);
144
147
  typeFactories.sort((a, b) => b.getPriority() - a.getPriority());
145
148
  this.typeToFactories.set(encryptionType, typeFactories);
146
- logger$h.debug("registered_encryption_manager_factory", {
149
+ logger$i.debug("registered_encryption_manager_factory", {
147
150
  factory: factory.constructor.name,
148
151
  encryption_type: encryptionType,
149
152
  algorithms: factory.getSupportedAlgorithms(),
@@ -159,14 +162,14 @@ class EncryptionManagerFactoryRegistry {
159
162
  this.ensureAutoDiscovery();
160
163
  for (const factory of this.factories) {
161
164
  if (factory.supportsOptions(opts ?? undefined)) {
162
- logger$h.debug("found_factory_for_options", {
165
+ logger$i.debug("found_factory_for_options", {
163
166
  factory: factory.constructor.name,
164
167
  encryption_type: factory.getEncryptionType(),
165
168
  });
166
169
  return factory;
167
170
  }
168
171
  }
169
- logger$h.debug("no_factory_found_for_options", { opts });
172
+ logger$i.debug("no_factory_found_for_options", { opts });
170
173
  return undefined;
171
174
  }
172
175
  getFactoriesByType(encryptionType) {
@@ -291,10 +294,87 @@ var strictOverlaySecurityProfile = /*#__PURE__*/Object.freeze({
291
294
  PROFILE_NAME_STRICT_OVERLAY: PROFILE_NAME_STRICT_OVERLAY
292
295
  });
293
296
 
297
+ /**
298
+ * HTTP Policy Authorization Profile
299
+ *
300
+ * Provides the 'policy-http' authorization profile for loading policies over HTTP(S).
301
+ * This profile is similar to 'policy-localfile' from the runtime package but uses
302
+ * the HttpAuthorizationPolicySource instead of LocalFileAuthorizationPolicySource.
303
+ */
304
+ // Environment variable names for HTTP policy source
305
+ const ENV_VAR_AUTH_POLICY_URL = "FAME_AUTH_POLICY_URL";
306
+ const ENV_VAR_AUTH_POLICY_TIMEOUT_MS = "FAME_AUTH_POLICY_TIMEOUT_MS";
307
+ const ENV_VAR_AUTH_POLICY_CACHE_TTL_MS = "FAME_AUTH_POLICY_CACHE_TTL_MS";
308
+ const ENV_VAR_AUTH_POLICY_TOKEN_URL = "FAME_AUTH_POLICY_TOKEN_URL";
309
+ const ENV_VAR_AUTH_POLICY_CLIENT_ID = "FAME_AUTH_POLICY_CLIENT_ID";
310
+ const ENV_VAR_AUTH_POLICY_CLIENT_SECRET = "FAME_AUTH_POLICY_CLIENT_SECRET";
311
+ const ENV_VAR_AUTH_POLICY_AUDIENCE = "FAME_AUTH_POLICY_AUDIENCE";
312
+ // Legacy environment variable for backwards compatibility
313
+ const ENV_VAR_AUTH_POLICY_BEARER_TOKEN = "FAME_AUTH_POLICY_BEARER_TOKEN";
314
+ // Profile name constant
315
+ const PROFILE_NAME_POLICY_HTTP = "policy-http";
316
+ // Re-use JWT verifier env vars from runtime
317
+ const ENV_VAR_JWKS_URL = "FAME_JWKS_URL";
318
+ const ENV_VAR_JWT_TRUSTED_ISSUER = "FAME_JWT_TRUSTED_ISSUER";
319
+ /**
320
+ * Default token verifier configuration using JWKS.
321
+ */
322
+ const DEFAULT_VERIFIER_CONFIG = {
323
+ type: "JWKSJWTTokenVerifier",
324
+ jwks_url: factory.Expressions.env(ENV_VAR_JWKS_URL),
325
+ issuer: factory.Expressions.env(ENV_VAR_JWT_TRUSTED_ISSUER),
326
+ };
327
+ /**
328
+ * Creates OAuth2 token provider configuration for HTTP policy source.
329
+ *
330
+ * Uses environment variables for OAuth2 client credentials flow.
331
+ */
332
+ function createOAuth2TokenProviderConfig() {
333
+ const tokenUrl = factory.Expressions.env(ENV_VAR_AUTH_POLICY_TOKEN_URL);
334
+ const clientId = factory.Expressions.env(ENV_VAR_AUTH_POLICY_CLIENT_ID);
335
+ const clientSecret = factory.Expressions.env(ENV_VAR_AUTH_POLICY_CLIENT_SECRET);
336
+ const audience = factory.Expressions.env(ENV_VAR_AUTH_POLICY_AUDIENCE);
337
+ return {
338
+ type: "OAuth2ClientCredentialsTokenProvider",
339
+ token_url: tokenUrl,
340
+ tokenUrl,
341
+ client_id: clientId,
342
+ clientId,
343
+ client_secret: clientSecret,
344
+ clientSecret,
345
+ scopes: ["policy.read"],
346
+ audience,
347
+ };
348
+ }
349
+ /**
350
+ * Default HTTP policy source configuration.
351
+ *
352
+ * Uses environment variables for URL, timeout, and OAuth2 client credentials.
353
+ */
354
+ const DEFAULT_HTTP_POLICY_SOURCE = {
355
+ type: "HttpAuthorizationPolicySource",
356
+ url: factory.Expressions.env(ENV_VAR_AUTH_POLICY_URL),
357
+ timeout_ms: factory.Expressions.env(ENV_VAR_AUTH_POLICY_TIMEOUT_MS, "30000"),
358
+ cache_ttl_ms: factory.Expressions.env(ENV_VAR_AUTH_POLICY_CACHE_TTL_MS, "300000"),
359
+ // OAuth2 client credentials token provider
360
+ token_provider: createOAuth2TokenProviderConfig(),
361
+ };
362
+ const POLICY_HTTP_PROFILE = {
363
+ type: "PolicyAuthorizer",
364
+ verifier: DEFAULT_VERIFIER_CONFIG,
365
+ policy_source: DEFAULT_HTTP_POLICY_SOURCE,
366
+ };
367
+ // Register the policy-http profile
368
+ runtime.registerProfile(runtime.AUTHORIZER_FACTORY_BASE_TYPE, PROFILE_NAME_POLICY_HTTP, POLICY_HTTP_PROFILE, {
369
+ source: "advanced-security:policy-http-authorization-profile",
370
+ allowOverride: true,
371
+ });
372
+
294
373
  const SECURITY_PREFIX = "./security/";
295
374
  const SECURITY_MODULES = MODULES.filter((spec) => spec.startsWith(SECURITY_PREFIX));
296
375
  const EXTRA_MODULES = MODULES.filter((spec) => !spec.startsWith(SECURITY_PREFIX));
297
376
  const NODE_ONLY_MODULES = new Set([
377
+ "./security/auth/policy/http-authorization-policy-source-factory.js",
298
378
  "./security/cert/default-ca-service-factory.js",
299
379
  "./security/cert/trust-store/node-trust-store-provider-factory.js",
300
380
  ]);
@@ -575,12 +655,12 @@ async function registerAdvancedSecurityFactories(registrar = factory.Registry, o
575
655
  }
576
656
 
577
657
  // This file is auto-generated during build - do not edit manually
578
- // Generated from package.json version: 0.4.4
658
+ // Generated from package.json version: 0.4.6
579
659
  /**
580
660
  * The package version, injected at build time.
581
661
  * @internal
582
662
  */
583
- const VERSION = '0.4.4';
663
+ const VERSION = '0.4.6';
584
664
 
585
665
  async function registerAdvancedSecurityPluginFactories(registrar = factory.Registry) {
586
666
  await registerAdvancedSecurityFactories(registrar, { includeExtras: true });
@@ -1985,7 +2065,7 @@ const secure_hash = (args) => {
1985
2065
  }
1986
2066
  // Use generateFingerprintSync from @naylence/core
1987
2067
  // This provides SHA-256 hashing, base62 encoding, and profanity filtering
1988
- return core.generateFingerprintSync(input_str, length, sha256.sha256);
2068
+ return core.generateFingerprintSync(input_str, length, sha2.sha256);
1989
2069
  };
1990
2070
  // ============================================================
1991
2071
  // Pattern Helpers (BSL-only)
@@ -2559,8 +2639,86 @@ function evaluateAsBoolean(ast, context) {
2559
2639
  * Null handling semantics:
2560
2640
  * - Scope predicate builtins (has_scope, has_any_scope, has_all_scopes)
2561
2641
  * return `false` when passed `null` for required args.
2642
+ * - Security predicate builtins (is_signed, is_encrypted, is_encrypted_at_least)
2643
+ * return `false` when the envelope lacks the required security posture.
2562
2644
  * - Wrong non-null types still raise BuiltinError to surface real bugs.
2563
2645
  */
2646
+ /**
2647
+ * Valid encryption levels for is_encrypted_at_least comparisons.
2648
+ */
2649
+ const VALID_ENCRYPTION_LEVELS = [
2650
+ "plaintext",
2651
+ "channel",
2652
+ "sealed",
2653
+ ];
2654
+ /**
2655
+ * Encryption level ordering for comparison.
2656
+ * Higher number = stronger encryption.
2657
+ */
2658
+ const ENCRYPTION_LEVEL_ORDER = {
2659
+ plaintext: 0,
2660
+ channel: 1,
2661
+ sealed: 2,
2662
+ };
2663
+ /**
2664
+ * Normalizes an encryption algorithm string to an EncryptionLevel.
2665
+ *
2666
+ * Mapping rules:
2667
+ * - null/undefined => "plaintext" (no encryption present)
2668
+ * - alg contains "-channel" => "channel" (e.g., "chacha20-poly1305-channel")
2669
+ * - alg contains "-sealed" => "sealed" (explicit sealed marker)
2670
+ * - alg matches ECDH-ES pattern with AEAD cipher => "sealed" (e.g., "ECDH-ES+A256GCM")
2671
+ * - otherwise => "unknown"
2672
+ *
2673
+ * Currently supported algorithms:
2674
+ * - Channel: "chacha20-poly1305-channel"
2675
+ * - Sealed: "ECDH-ES+A256GCM"
2676
+ *
2677
+ * This helper is centralized to ensure consistent mapping across TS and Python.
2678
+ */
2679
+ function normalizeEncryptionLevelFromAlg(alg) {
2680
+ if (alg === null || alg === undefined) {
2681
+ return "plaintext";
2682
+ }
2683
+ const algLower = alg.toLowerCase();
2684
+ // Check for channel encryption (e.g., "chacha20-poly1305-channel")
2685
+ // Must check before other patterns since channel suffix is explicit
2686
+ if (algLower.includes("-channel")) {
2687
+ return "channel";
2688
+ }
2689
+ // Check for explicit sealed marker
2690
+ if (algLower.includes("-sealed")) {
2691
+ return "sealed";
2692
+ }
2693
+ // ECDH-ES key agreement with AEAD cipher => sealed encryption
2694
+ // Pattern: "ECDH-ES+A256GCM", "ECDH-ES+A128GCM", etc.
2695
+ if (algLower.startsWith("ecdh-es") && algLower.includes("+a")) {
2696
+ return "sealed";
2697
+ }
2698
+ return "unknown";
2699
+ }
2700
+ /**
2701
+ * Creates security bindings from an envelope's sec header.
2702
+ * Exposes only metadata, never raw values like sig.val or enc.val.
2703
+ */
2704
+ function createSecurityBindings(sec) {
2705
+ const sigPresent = sec?.sig !== undefined;
2706
+ const encPresent = sec?.enc !== undefined;
2707
+ return {
2708
+ sig: {
2709
+ present: sigPresent,
2710
+ kid: sec?.sig?.kid ?? null,
2711
+ },
2712
+ enc: {
2713
+ present: encPresent,
2714
+ alg: sec?.enc?.alg ?? null,
2715
+ kid: sec?.enc?.kid ?? null,
2716
+ level: encPresent
2717
+ ? normalizeEncryptionLevelFromAlg(sec?.enc?.alg ?? null)
2718
+ : "plaintext",
2719
+ },
2720
+ };
2721
+ }
2564
2722
  /**
2565
2723
  * Checks if a value is null.
2566
2724
  */
@@ -2569,9 +2727,21 @@ function isNull(value) {
2569
2727
  }
2570
2728
  /**
2571
2729
  * Creates a function registry with auth helpers installed.
2730
+ *
2731
+ * This registry extends the base builtins with:
2732
+ * - Scope builtins: has_scope, has_any_scope, has_all_scopes
2733
+ * - Security builtins: is_signed, encryption_level, is_encrypted, is_encrypted_at_least
2572
2734
  */
2573
- function createAuthFunctionRegistry(grantedScopes = []) {
2574
- const scopes = grantedScopes ?? [];
2735
+ function createAuthFunctionRegistry(grantedScopesOrOptions = []) {
2736
+ // Handle both old signature (array) and new signature (options object)
2737
+ const options = Array.isArray(grantedScopesOrOptions)
2738
+ ? { grantedScopes: grantedScopesOrOptions }
2739
+ : grantedScopesOrOptions;
2740
+ const scopes = options.grantedScopes ?? [];
2741
+ const secBindings = options.securityBindings ?? {
2742
+ sig: { present: false, kid: null },
2743
+ enc: { present: false, alg: null, kid: null, level: "plaintext" },
2744
+ };
2575
2745
  /**
2576
2746
  * Checks if any granted scope matches a pattern (using glob syntax).
2577
2747
  */
@@ -2627,11 +2797,85 @@ function createAuthFunctionRegistry(grantedScopes = []) {
2627
2797
  }
2628
2798
  return values.every((scope) => matchesScope(scope));
2629
2799
  };
2800
+ // ============================================================
2801
+ // Security posture builtins
2802
+ // ============================================================
2803
+ /**
2804
+ * is_signed() -> bool
2805
+ *
2806
+ * Returns true if the envelope has a signature present.
2807
+ * No arguments required.
2808
+ */
2809
+ const is_signed = (args) => {
2810
+ assertArgCount(args, 0, "is_signed");
2811
+ return secBindings.sig.present;
2812
+ };
2813
+ /**
2814
+ * encryption_level() -> string
2815
+ *
2816
+ * Returns the normalized encryption level: "plaintext" | "channel" | "sealed" | "unknown"
2817
+ * No arguments required.
2818
+ */
2819
+ const encryption_level = (args) => {
2820
+ assertArgCount(args, 0, "encryption_level");
2821
+ return secBindings.enc.level;
2822
+ };
2823
+ /**
2824
+ * is_encrypted() -> bool
2825
+ *
2826
+ * Returns true if the encryption level is not "plaintext".
2827
+ * This means the envelope has some form of encryption (channel, sealed, or unknown).
2828
+ * No arguments required.
2829
+ */
2830
+ const is_encrypted = (args) => {
2831
+ assertArgCount(args, 0, "is_encrypted");
2832
+ return secBindings.enc.level !== "plaintext";
2833
+ };
2834
+ /**
2835
+ * is_encrypted_at_least(level: string) -> bool
2836
+ *
2837
+ * Returns true if the envelope's encryption level meets or exceeds the required level.
2838
+ *
2839
+ * Level ordering: plaintext < channel < sealed
2840
+ *
2841
+ * Special handling:
2842
+ * - "unknown" encryption level does NOT satisfy "channel" or "sealed" (conservative)
2843
+ * - "plaintext" is always satisfied (any envelope meets at least plaintext)
2844
+ * - null argument => false (predicate-style)
2845
+ * - invalid level string => BuiltinError
2846
+ */
2847
+ const is_encrypted_at_least = (args) => {
2848
+ assertArgCount(args, 1, "is_encrypted_at_least");
2849
+ const requiredLevel = getArg(args, 0, "is_encrypted_at_least");
2850
+ // Null-tolerant: return false if level is null
2851
+ if (!assertStringOrNull(requiredLevel, "level", "is_encrypted_at_least")) {
2852
+ return false;
2853
+ }
2854
+ // Validate required level
2855
+ if (!VALID_ENCRYPTION_LEVELS.includes(requiredLevel)) {
2856
+ throw new BuiltinError("is_encrypted_at_least", `level must be one of: ${VALID_ENCRYPTION_LEVELS.join(", ")}; got "${requiredLevel}"`);
2857
+ }
2858
+ const currentLevel = secBindings.enc.level;
2859
+ const requiredOrder = ENCRYPTION_LEVEL_ORDER[requiredLevel] ?? 0;
2860
+ const currentOrder = ENCRYPTION_LEVEL_ORDER[currentLevel];
2861
+ // If current level is "unknown", it only satisfies "plaintext"
2862
+ if (currentOrder === undefined) {
2863
+ // "unknown" is treated as NOT meeting channel/sealed requirements
2864
+ return requiredOrder === 0; // Only plaintext is satisfied by unknown
2865
+ }
2866
+ return currentOrder >= requiredOrder;
2867
+ };
2630
2868
  return new Map([
2631
2869
  ...BUILTIN_FUNCTIONS,
2870
+ // Scope builtins
2632
2871
  ["has_scope", has_scope],
2633
2872
  ["has_any_scope", has_any_scope],
2634
2873
  ["has_all_scopes", has_all_scopes],
2874
+ // Security posture builtins
2875
+ ["is_signed", is_signed],
2876
+ ["encryption_level", encryption_level],
2877
+ ["is_encrypted", is_encrypted],
2878
+ ["is_encrypted_at_least", is_encrypted_at_least],
2635
2879
  ]);
2636
2880
  }
2637
2881
  /**
@@ -2774,19 +3018,33 @@ function extractClaims(context) {
2774
3018
  }
2775
3019
  /**
2776
3020
  * Creates a safe envelope subset for expression bindings.
3021
+ *
3022
+ * Exposes:
3023
+ * - id, sid, traceId, corrId, flowId, to
3024
+ * - frame: { type }
3025
+ * - sec: { sig: { present, kid }, enc: { present, alg, kid, level } }
3026
+ *
3027
+ * IMPORTANT: Does NOT expose raw security values (sig.val, enc.val).
2777
3028
  */
2778
3029
  function createEnvelopeBindings(envelope) {
2779
3030
  const frame = envelope.frame;
2780
3031
  const envelopeRecord = envelope;
3032
+ const sec = envelopeRecord.sec;
3033
+ const securityBindings = createSecurityBindings(sec);
2781
3034
  return {
2782
- id: envelope.id ?? null,
2783
- traceId: envelopeRecord.traceId ?? null,
2784
- corrId: envelopeRecord.corrId ?? null,
2785
- flowId: envelopeRecord.flowId ?? null,
2786
- to: extractAddress(envelope) ?? null,
2787
- frame: frame
2788
- ? { type: frame.type ?? null }
2789
- : { type: null },
3035
+ bindings: {
3036
+ id: envelope.id ?? null,
3037
+ sid: envelopeRecord.sid ?? null,
3038
+ traceId: envelopeRecord.traceId ?? null,
3039
+ corrId: envelopeRecord.corrId ?? null,
3040
+ flowId: envelopeRecord.flowId ?? null,
3041
+ to: extractAddress(envelope) ?? null,
3042
+ frame: frame
3043
+ ? { type: frame.type ?? null }
3044
+ : { type: null },
3045
+ sec: securityBindings,
3046
+ },
3047
+ securityBindings,
2790
3048
  };
2791
3049
  }
2792
3050
  /**
@@ -2940,11 +3198,12 @@ class AdvancedAuthorizationPolicy {
2940
3198
  continue;
2941
3199
  }
2942
3200
  if (rule.whenAst) {
2943
- // Lazy initialization of expression bindings
3201
+ // Lazy initialization of expression bindings and security context
2944
3202
  if (!expressionBindings) {
3203
+ const envelopeResult = createEnvelopeBindings(envelope);
2945
3204
  expressionBindings = {
2946
3205
  claims: extractClaims(context),
2947
- envelope: createEnvelopeBindings(envelope),
3206
+ envelope: envelopeResult.bindings,
2948
3207
  delivery: createDeliveryBindings(context, resolvedAction),
2949
3208
  node: createNodeBindings(node),
2950
3209
  time: {
@@ -2952,9 +3211,13 @@ class AdvancedAuthorizationPolicy {
2952
3211
  now_iso: new Date().toISOString(),
2953
3212
  },
2954
3213
  };
3214
+ // Create function registry with security bindings for security builtins
3215
+ functionRegistry = createAuthFunctionRegistry({
3216
+ grantedScopes,
3217
+ securityBindings: envelopeResult.securityBindings,
3218
+ });
2955
3219
  }
2956
- const functions = functionRegistry ?? createAuthFunctionRegistry(grantedScopes);
2957
- functionRegistry = functions;
3220
+ const functions = functionRegistry;
2958
3221
  const evalContext = {
2959
3222
  bindings: expressionBindings,
2960
3223
  limits: this.expressionLimits,
@@ -3303,7 +3566,7 @@ function getModule() {
3303
3566
  }
3304
3567
  return modulePromise;
3305
3568
  }
3306
- function normalizeConfig$5(config) {
3569
+ function normalizeConfig$6(config) {
3307
3570
  if (!config) {
3308
3571
  throw new Error("AdvancedAuthorizationPolicyFactory requires a configuration with a policyDefinition");
3309
3572
  }
@@ -3332,7 +3595,7 @@ function normalizeConfig$5(config) {
3332
3595
  /**
3333
3596
  * Factory metadata for registration.
3334
3597
  */
3335
- const FACTORY_META$f = {
3598
+ const FACTORY_META$g = {
3336
3599
  base: runtime.AUTHORIZATION_POLICY_FACTORY_BASE_TYPE,
3337
3600
  key: "AdvancedAuthorizationPolicy",
3338
3601
  };
@@ -3351,7 +3614,7 @@ class AdvancedAuthorizationPolicyFactory extends runtime.AuthorizationPolicyFact
3351
3614
  * @returns The created authorization policy
3352
3615
  */
3353
3616
  async create(config) {
3354
- const normalized = normalizeConfig$5(config);
3617
+ const normalized = normalizeConfig$6(config);
3355
3618
  const { AdvancedAuthorizationPolicy } = await getModule();
3356
3619
  return new AdvancedAuthorizationPolicy({
3357
3620
  policyDefinition: normalized.policyDefinition,
@@ -3364,10 +3627,493 @@ class AdvancedAuthorizationPolicyFactory extends runtime.AuthorizationPolicyFact
3364
3627
  var advancedAuthorizationPolicyFactory = /*#__PURE__*/Object.freeze({
3365
3628
  __proto__: null,
3366
3629
  AdvancedAuthorizationPolicyFactory: AdvancedAuthorizationPolicyFactory,
3367
- FACTORY_META: FACTORY_META$f,
3630
+ FACTORY_META: FACTORY_META$g,
3368
3631
  default: AdvancedAuthorizationPolicyFactory
3369
3632
  });
3370
3633
 
3634
+ /**
3635
+ * HTTP-based authorization policy source.
3636
+ *
3637
+ * Loads authorization policies from an HTTP endpoint supporting JSON or YAML.
3638
+ * Supports bearer authentication via TokenProvider and HTTP caching via ETag.
3639
+ *
3640
+ * This is a Node.js-only implementation.
3641
+ *
3642
+ * @packageDocumentation
3643
+ */
3644
+ const logger$h = runtime.getLogger("naylence.fame.security.auth.policy.http_authorization_policy_source");
3645
+ function isPlainObject(value) {
3646
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
3647
+ }
3648
+ function parseJson(content) {
3649
+ const parsed = JSON.parse(content);
3650
+ if (!isPlainObject(parsed)) {
3651
+ throw new Error("Parsed JSON policy must be an object");
3652
+ }
3653
+ return parsed;
3654
+ }
3655
+ function parseYamlContent(content) {
3656
+ const parsed = yaml.parse(content ?? "");
3657
+ if (parsed == null) {
3658
+ return {};
3659
+ }
3660
+ if (!isPlainObject(parsed)) {
3661
+ throw new Error("Parsed YAML policy must be an object");
3662
+ }
3663
+ return parsed;
3664
+ }
3665
+ /**
3666
+ * Detect whether content is JSON or YAML based on Content-Type header.
3667
+ * Falls back to sniffing the content if Content-Type is not definitive.
3668
+ */
3669
+ function detectFormat(contentType, content) {
3670
+ if (contentType) {
3671
+ const lower = contentType.toLowerCase();
3672
+ if (lower.includes("application/json") ||
3673
+ lower.includes("text/json")) {
3674
+ return "json";
3675
+ }
3676
+ if (lower.includes("application/yaml") ||
3677
+ lower.includes("application/x-yaml") ||
3678
+ lower.includes("text/yaml") ||
3679
+ lower.includes("text/x-yaml")) {
3680
+ return "yaml";
3681
+ }
3682
+ }
3683
+ // Sniff by first non-whitespace character
3684
+ const trimmed = content.trimStart();
3685
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
3686
+ return "json";
3687
+ }
3688
+ // Default to YAML
3689
+ return "yaml";
3690
+ }
3691
+ /**
3692
+ * Parse Cache-Control header to extract max-age value.
3693
+ */
3694
+ function parseMaxAge(cacheControl) {
3695
+ if (!cacheControl) {
3696
+ return undefined;
3697
+ }
3698
+ const match = cacheControl.match(/max-age\s*=\s*(\d+)/i);
3699
+ if (match && match[1]) {
3700
+ const seconds = parseInt(match[1], 10);
3701
+ if (Number.isFinite(seconds) && seconds >= 0) {
3702
+ return seconds;
3703
+ }
3704
+ }
3705
+ return undefined;
3706
+ }
3707
+ /**
3708
+ * An authorization policy source that loads policy definitions from an HTTP endpoint.
3709
+ *
3710
+ * Supports JSON and YAML formats, bearer authentication via TokenProvider,
3711
+ * and HTTP caching via ETag and Cache-Control headers.
3712
+ *
3713
+ * This is a Node.js-only implementation that uses fetch.
3714
+ */
3715
+ class HttpAuthorizationPolicySource {
3716
+ constructor(options) {
3717
+ this.cachedState = null;
3718
+ this.inflightFetch = null;
3719
+ if (!options.url || typeof options.url !== "string") {
3720
+ throw new Error("HttpAuthorizationPolicySource requires a valid URL");
3721
+ }
3722
+ this.url = options.url;
3723
+ this.method = options.method ?? "GET";
3724
+ this.timeoutMs = options.timeoutMs ?? 30000;
3725
+ this.headers = { ...options.headers };
3726
+ this.tokenProvider = options.tokenProvider;
3727
+ this.bearerPrefix = options.bearerPrefix ?? "Bearer ";
3728
+ this.policyFactoryConfig = options.policyFactory;
3729
+ this.cacheTtlMs = options.cacheTtlMs ?? 300000; // 5 minutes default
3730
+ }
3731
+ /**
3732
+ * Loads the authorization policy from the configured HTTP endpoint.
3733
+ *
3734
+ * Returns a cached policy if still fresh (based on TTL or cache headers).
3735
+ * Multiple concurrent calls are de-duplicated (single-flight pattern).
3736
+ *
3737
+ * @returns The loaded authorization policy
3738
+ */
3739
+ async loadPolicy() {
3740
+ // Return cached policy if still fresh
3741
+ if (this.cachedState && this.isCacheFresh()) {
3742
+ logger$h.debug("returning_cached_policy", {
3743
+ url: this.url,
3744
+ fetchedAt: this.cachedState.metadata.fetchedAt,
3745
+ expiresAt: this.cachedState.metadata.expiresAt,
3746
+ });
3747
+ return this.cachedState.policy;
3748
+ }
3749
+ // De-duplicate concurrent requests
3750
+ if (this.inflightFetch) {
3751
+ return this.inflightFetch;
3752
+ }
3753
+ this.inflightFetch = this.fetchPolicy(false);
3754
+ try {
3755
+ return await this.inflightFetch;
3756
+ }
3757
+ finally {
3758
+ this.inflightFetch = null;
3759
+ }
3760
+ }
3761
+ /**
3762
+ * Forces a reload of the policy from the HTTP endpoint.
3763
+ *
3764
+ * Bypasses cache freshness checks and always fetches from the server.
3765
+ * If the fetch fails, the existing cached policy is preserved and the error is thrown.
3766
+ *
3767
+ * @returns The reloaded authorization policy
3768
+ */
3769
+ async reloadPolicy() {
3770
+ // Clear inflight to force a new request
3771
+ this.inflightFetch = null;
3772
+ return this.fetchPolicy(true);
3773
+ }
3774
+ /**
3775
+ * Clears the cached policy, forcing a fresh fetch on the next loadPolicy() call.
3776
+ */
3777
+ clearCache() {
3778
+ this.cachedState = null;
3779
+ this.inflightFetch = null;
3780
+ }
3781
+ /**
3782
+ * Returns metadata about the last successful fetch.
3783
+ *
3784
+ * Useful for verification, monitoring, or debugging.
3785
+ */
3786
+ getMetadata() {
3787
+ return this.cachedState?.metadata;
3788
+ }
3789
+ /**
3790
+ * Returns the raw policy definition from the last successful fetch.
3791
+ *
3792
+ * Useful for verification or reprocessing.
3793
+ */
3794
+ getRawDefinition() {
3795
+ return this.cachedState?.rawDefinition;
3796
+ }
3797
+ isCacheFresh() {
3798
+ if (!this.cachedState) {
3799
+ return false;
3800
+ }
3801
+ const now = Date.now();
3802
+ const { expiresAt } = this.cachedState.metadata;
3803
+ if (expiresAt !== undefined) {
3804
+ return now < expiresAt;
3805
+ }
3806
+ // No expiration info, check against default TTL
3807
+ const fetchedAt = this.cachedState.metadata.fetchedAt;
3808
+ return now < fetchedAt + this.cacheTtlMs;
3809
+ }
3810
+ async fetchPolicy(forceRefresh) {
3811
+ logger$h.debug("fetching_policy", {
3812
+ url: this.url,
3813
+ method: this.method,
3814
+ forceRefresh,
3815
+ });
3816
+ const requestHeaders = {
3817
+ Accept: "application/json, application/yaml, text/yaml, */*",
3818
+ ...this.headers,
3819
+ };
3820
+ // Add bearer token if token provider is configured
3821
+ if (this.tokenProvider) {
3822
+ try {
3823
+ const token = await this.tokenProvider.getToken();
3824
+ if (token && token.value) {
3825
+ requestHeaders["Authorization"] = `${this.bearerPrefix}${token.value}`;
3826
+ logger$h.debug("added_bearer_token", { url: this.url });
3827
+ }
3828
+ }
3829
+ catch (error) {
3830
+ logger$h.warning("token_provider_failed", {
3831
+ url: this.url,
3832
+ error: error instanceof Error ? error.message : String(error),
3833
+ });
3834
+ // Continue without token - let the server decide if auth is required
3835
+ }
3836
+ }
3837
+ // Add If-None-Match header for conditional request if we have a cached ETag
3838
+ // and this is not a forced refresh
3839
+ if (!forceRefresh && this.cachedState?.metadata.etag) {
3840
+ requestHeaders["If-None-Match"] = this.cachedState.metadata.etag;
3841
+ }
3842
+ const controller = new AbortController();
3843
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
3844
+ try {
3845
+ const response = await fetch(this.url, {
3846
+ method: this.method,
3847
+ headers: requestHeaders,
3848
+ signal: controller.signal,
3849
+ });
3850
+ clearTimeout(timeoutId);
3851
+ // Handle 304 Not Modified - return cached policy
3852
+ if (response.status === 304 && this.cachedState) {
3853
+ logger$h.debug("policy_not_modified", {
3854
+ url: this.url,
3855
+ etag: this.cachedState.metadata.etag,
3856
+ });
3857
+ // Update freshness timestamps
3858
+ const now = Date.now();
3859
+ const cacheControl = response.headers.get("Cache-Control");
3860
+ const maxAgeSeconds = parseMaxAge(cacheControl);
3861
+ const expiresAt = maxAgeSeconds !== undefined
3862
+ ? now + maxAgeSeconds * 1000
3863
+ : now + this.cacheTtlMs;
3864
+ this.cachedState = {
3865
+ ...this.cachedState,
3866
+ metadata: {
3867
+ ...this.cachedState.metadata,
3868
+ fetchedAt: now,
3869
+ maxAgeSeconds,
3870
+ expiresAt,
3871
+ },
3872
+ };
3873
+ return this.cachedState.policy;
3874
+ }
3875
+ if (!response.ok) {
3876
+ const errorMessage = `HTTP ${response.status}: ${response.statusText}`;
3877
+ logger$h.error("policy_fetch_failed", {
3878
+ url: this.url,
3879
+ status: response.status,
3880
+ statusText: response.statusText,
3881
+ });
3882
+ // If we have a cached policy, preserve it and throw
3883
+ if (this.cachedState) {
3884
+ throw new Error(`Failed to fetch policy from ${this.url}: ${errorMessage}. ` +
3885
+ "Using last known good policy.");
3886
+ }
3887
+ throw new Error(`Failed to fetch policy from ${this.url}: ${errorMessage}`);
3888
+ }
3889
+ // Parse the response
3890
+ const contentType = response.headers.get("Content-Type");
3891
+ const content = await response.text();
3892
+ const format = detectFormat(contentType, content);
3893
+ let policyDefinition;
3894
+ try {
3895
+ if (format === "json") {
3896
+ policyDefinition = parseJson(content);
3897
+ }
3898
+ else {
3899
+ policyDefinition = parseYamlContent(content);
3900
+ }
3901
+ }
3902
+ catch (parseError) {
3903
+ const message = parseError instanceof Error
3904
+ ? parseError.message
3905
+ : String(parseError);
3906
+ logger$h.error("policy_parse_failed", {
3907
+ url: this.url,
3908
+ format,
3909
+ error: message,
3910
+ });
3911
+ // Preserve cached policy on parse failure
3912
+ if (this.cachedState) {
3913
+ throw new Error(`Failed to parse policy from ${this.url}: ${message}. ` +
3914
+ "Using last known good policy.");
3915
+ }
3916
+ throw new Error(`Failed to parse policy from ${this.url}: ${message}`);
3917
+ }
3918
+ logger$h.debug("parsed_policy_definition", {
3919
+ url: this.url,
3920
+ format,
3921
+ hasType: "type" in policyDefinition,
3922
+ });
3923
+ // Build the policy using the factory
3924
+ const policy = await this.buildPolicy(policyDefinition);
3925
+ // Update cache
3926
+ const now = Date.now();
3927
+ const etag = response.headers.get("ETag") ?? undefined;
3928
+ const cacheControl = response.headers.get("Cache-Control");
3929
+ const maxAgeSeconds = parseMaxAge(cacheControl);
3930
+ const expiresAt = maxAgeSeconds !== undefined
3931
+ ? now + maxAgeSeconds * 1000
3932
+ : now + this.cacheTtlMs;
3933
+ this.cachedState = {
3934
+ policy,
3935
+ rawDefinition: policyDefinition,
3936
+ metadata: {
3937
+ url: this.url,
3938
+ status: response.status,
3939
+ etag,
3940
+ fetchedAt: now,
3941
+ maxAgeSeconds,
3942
+ expiresAt,
3943
+ },
3944
+ };
3945
+ logger$h.info("loaded_policy_from_http", {
3946
+ url: this.url,
3947
+ status: response.status,
3948
+ format,
3949
+ etag,
3950
+ maxAgeSeconds,
3951
+ });
3952
+ return policy;
3953
+ }
3954
+ catch (error) {
3955
+ clearTimeout(timeoutId);
3956
+ if (error instanceof Error && error.name === "AbortError") {
3957
+ const timeoutError = new Error(`Request to ${this.url} timed out after ${this.timeoutMs}ms`);
3958
+ logger$h.error("policy_fetch_timeout", {
3959
+ url: this.url,
3960
+ timeoutMs: this.timeoutMs,
3961
+ });
3962
+ // Preserve cached policy on timeout
3963
+ if (this.cachedState) {
3964
+ throw timeoutError;
3965
+ }
3966
+ throw timeoutError;
3967
+ }
3968
+ throw error;
3969
+ }
3970
+ }
3971
+ async buildPolicy(policyDefinition) {
3972
+ // Determine the factory configuration to use
3973
+ const factoryConfig = this.policyFactoryConfig ?? policyDefinition;
3974
+ // Ensure we have a type field for the factory
3975
+ if (!("type" in factoryConfig) || typeof factoryConfig.type !== "string") {
3976
+ logger$h.warning("policy_type_missing_defaulting_to_basic", {
3977
+ url: this.url,
3978
+ });
3979
+ factoryConfig.type = "BasicAuthorizationPolicy";
3980
+ }
3981
+ // Build the factory config with the policy definition
3982
+ // The response content IS the policy definition, so we extract the type
3983
+ // and wrap the remaining content as the policyDefinition
3984
+ const { type: definitionType, ...restOfDefinition } = policyDefinition;
3985
+ const resolvedType = typeof definitionType === "string" && definitionType.trim().length > 0
3986
+ ? definitionType
3987
+ : factoryConfig.type;
3988
+ const mergedConfig = this.policyFactoryConfig != null
3989
+ ? { ...this.policyFactoryConfig, policyDefinition }
3990
+ : { type: resolvedType, policyDefinition: restOfDefinition };
3991
+ const policy = await runtime.AuthorizationPolicyFactory.createAuthorizationPolicy(mergedConfig);
3992
+ if (!policy) {
3993
+ throw new Error(`Failed to create authorization policy from ${this.url}`);
3994
+ }
3995
+ return policy;
3996
+ }
3997
+ }
3998
+
3999
+ var httpAuthorizationPolicySource = /*#__PURE__*/Object.freeze({
4000
+ __proto__: null,
4001
+ HttpAuthorizationPolicySource: HttpAuthorizationPolicySource
4002
+ });
4003
+
4004
+ /**
4005
+ * Factory for creating HttpAuthorizationPolicySource instances.
4006
+ *
4007
+ * @packageDocumentation
4008
+ */
4009
+ let httpModulePromise = null;
4010
+ async function getHttpModule() {
4011
+ if (!httpModulePromise) {
4012
+ httpModulePromise = Promise.resolve().then(function () { return httpAuthorizationPolicySource; });
4013
+ }
4014
+ return httpModulePromise;
4015
+ }
4016
+ function normalizeConfig$5(config) {
4017
+ if (!config) {
4018
+ throw new Error("HttpAuthorizationPolicySourceFactory requires a configuration with a url");
4019
+ }
4020
+ const candidate = config;
4021
+ const url = candidate.url;
4022
+ if (typeof url !== "string" || url.trim().length === 0) {
4023
+ throw new Error("HttpAuthorizationPolicySourceConfig requires a non-empty url");
4024
+ }
4025
+ // Support both camelCase and snake_case
4026
+ const method = candidate.method ?? "GET";
4027
+ if (!["GET", "POST", "PUT"].includes(method)) {
4028
+ throw new Error(`Invalid method "${String(method)}". Must be "GET", "POST", or "PUT"`);
4029
+ }
4030
+ const timeoutMs = candidate.timeout_ms ??
4031
+ candidate.timeoutMs ??
4032
+ 30000;
4033
+ if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0) {
4034
+ throw new Error("timeout_ms must be a positive number");
4035
+ }
4036
+ const headers = candidate.headers;
4037
+ if (headers !== undefined && typeof headers !== "object") {
4038
+ throw new Error("headers must be an object");
4039
+ }
4040
+ const tokenProviderConfig = candidate.token_provider ??
4041
+ candidate.tokenProvider;
4042
+ const bearerPrefix = candidate.bearer_prefix ??
4043
+ candidate.bearerPrefix ??
4044
+ "Bearer ";
4045
+ const policyFactory = candidate.policy_factory ??
4046
+ candidate.policyFactory;
4047
+ const cacheTtlMs = candidate.cache_ttl_ms ??
4048
+ candidate.cacheTtlMs ??
4049
+ 300000;
4050
+ if (typeof cacheTtlMs !== "number" || !Number.isFinite(cacheTtlMs) || cacheTtlMs < 0) {
4051
+ throw new Error("cache_ttl_ms must be a non-negative number");
4052
+ }
4053
+ return {
4054
+ url: url.trim(),
4055
+ method,
4056
+ timeoutMs,
4057
+ headers,
4058
+ tokenProviderConfig,
4059
+ bearerPrefix,
4060
+ policyFactory,
4061
+ cacheTtlMs,
4062
+ };
4063
+ }
4064
+ /**
4065
+ * Factory metadata for registration.
4066
+ */
4067
+ const FACTORY_META$f = {
4068
+ base: runtime.AUTHORIZATION_POLICY_SOURCE_FACTORY_BASE_TYPE,
4069
+ key: "HttpAuthorizationPolicySource",
4070
+ };
4071
+ /**
4072
+ * Factory for creating HttpAuthorizationPolicySource instances.
4073
+ *
4074
+ * This factory uses lazy loading to avoid pulling in Node.js-specific
4075
+ * code (fetch operations) in browser environments where it may not work.
4076
+ */
4077
+ class HttpAuthorizationPolicySourceFactory extends runtime.AuthorizationPolicySourceFactory {
4078
+ constructor() {
4079
+ super(...arguments);
4080
+ this.type = "HttpAuthorizationPolicySource";
4081
+ }
4082
+ /**
4083
+ * Creates an HttpAuthorizationPolicySource from the given configuration.
4084
+ *
4085
+ * @param config - Configuration specifying the policy URL and options
4086
+ * @returns The created policy source
4087
+ */
4088
+ async create(config) {
4089
+ const normalized = normalizeConfig$5(config);
4090
+ // Create token provider if configured
4091
+ let tokenProvider;
4092
+ if (normalized.tokenProviderConfig) {
4093
+ tokenProvider = await runtime.TokenProviderFactory.createTokenProvider(normalized.tokenProviderConfig);
4094
+ }
4095
+ const { HttpAuthorizationPolicySource } = await getHttpModule();
4096
+ const options = {
4097
+ url: normalized.url,
4098
+ method: normalized.method,
4099
+ timeoutMs: normalized.timeoutMs,
4100
+ headers: normalized.headers,
4101
+ tokenProvider,
4102
+ bearerPrefix: normalized.bearerPrefix,
4103
+ policyFactory: normalized.policyFactory,
4104
+ cacheTtlMs: normalized.cacheTtlMs,
4105
+ };
4106
+ return new HttpAuthorizationPolicySource(options);
4107
+ }
4108
+ }
4109
+
4110
+ var httpAuthorizationPolicySourceFactory = /*#__PURE__*/Object.freeze({
4111
+ __proto__: null,
4112
+ FACTORY_META: FACTORY_META$f,
4113
+ HttpAuthorizationPolicySourceFactory: HttpAuthorizationPolicySourceFactory,
4114
+ default: HttpAuthorizationPolicySourceFactory
4115
+ });
4116
+
3371
4117
  /**
3372
4118
  * Advanced authorization policy module exports.
3373
4119
  *
@@ -3376,7 +4122,7 @@ var advancedAuthorizationPolicyFactory = /*#__PURE__*/Object.freeze({
3376
4122
  *
3377
4123
  * @packageDocumentation
3378
4124
  */
3379
- // Auth expression helpers
4125
+ // Expression authorization policy
3380
4126
 
3381
4127
  /**
3382
4128
  * Advanced security authentication/authorization module exports.
@@ -13001,7 +13747,7 @@ if (isNode && proc && proc.env) {
13001
13747
  }
13002
13748
  }
13003
13749
 
13004
- exports.ADVANCED_AUTHORIZATION_POLICY_FACTORY_META = FACTORY_META$f;
13750
+ exports.ADVANCED_AUTHORIZATION_POLICY_FACTORY_META = FACTORY_META$g;
13005
13751
  exports.ADVANCED_EDDSA_ENVELOPE_SIGNER_FACTORY_META = FACTORY_META$a;
13006
13752
  exports.ADVANCED_EDDSA_ENVELOPE_VERIFIER_FACTORY_META = FACTORY_META$9;
13007
13753
  exports.ADVANCED_WELCOME_FACTORY_META = FACTORY_META$5;
@@ -13019,9 +13765,7 @@ exports.AdvancedEdDSAEnvelopeVerifierFactory = AdvancedEdDSAEnvelopeVerifierFact
13019
13765
  exports.AdvancedWelcomeService = AdvancedWelcomeService;
13020
13766
  exports.AdvancedWelcomeServiceFactory = AdvancedWelcomeServiceFactory;
13021
13767
  exports.BROWSER_TRUST_STORE_PROVIDER_FACTORY_META = FACTORY_META$2;
13022
- exports.BUILTIN_FUNCTIONS = BUILTIN_FUNCTIONS;
13023
13768
  exports.BrowserTrustStoreProviderFactory = BrowserTrustStoreProviderFactory;
13024
- exports.BuiltinError = BuiltinError;
13025
13769
  exports.CAService = CAService;
13026
13770
  exports.CAServiceClient = CAServiceClient;
13027
13771
  exports.CAServiceFactory = CAServiceFactory;
@@ -13031,7 +13775,6 @@ exports.CertificateRequestError = CertificateRequestError;
13031
13775
  exports.CompositeEncryptionManager = CompositeEncryptionManager;
13032
13776
  exports.CompositeEncryptionManagerFactory = CompositeEncryptionManagerFactory;
13033
13777
  exports.DEFAULT_CERTIFICATE_MANAGER_FACTORY_META = FACTORY_META$4;
13034
- exports.DEFAULT_EXPRESSION_LIMITS = DEFAULT_EXPRESSION_LIMITS;
13035
13778
  exports.DEFAULT_SECURE_CHANNEL_MANAGER_FACTORY_META = FACTORY_META$c;
13036
13779
  exports.DEFAULT_STICKINESS_SECURITY_LEVEL = DEFAULT_STICKINESS_SECURITY_LEVEL;
13037
13780
  exports.DefaultCAService = DefaultCAService;
@@ -13051,62 +13794,47 @@ exports.ENV_FAME_SIGNING_CERT_PEM = ENV_FAME_SIGNING_CERT_PEM;
13051
13794
  exports.ENV_FAME_SIGNING_KEY_FILE = ENV_FAME_SIGNING_KEY_FILE;
13052
13795
  exports.ENV_FAME_SIGNING_KEY_PEM = ENV_FAME_SIGNING_KEY_PEM;
13053
13796
  exports.ENV_TRUST_STORE_PROVIDER_FACTORY_META = FACTORY_META$3;
13797
+ exports.ENV_VAR_AUTH_POLICY_BEARER_TOKEN = ENV_VAR_AUTH_POLICY_BEARER_TOKEN;
13798
+ exports.ENV_VAR_AUTH_POLICY_CACHE_TTL_MS = ENV_VAR_AUTH_POLICY_CACHE_TTL_MS;
13799
+ exports.ENV_VAR_AUTH_POLICY_TIMEOUT_MS = ENV_VAR_AUTH_POLICY_TIMEOUT_MS;
13800
+ exports.ENV_VAR_AUTH_POLICY_URL = ENV_VAR_AUTH_POLICY_URL;
13054
13801
  exports.ENV_VAR_FAME_CA_SERVICE_URL = ENV_VAR_FAME_CA_SERVICE_URL;
13055
13802
  exports.EdDSAEnvelopeVerifier = EdDSAEnvelopeVerifier;
13056
13803
  exports.EnvTrustStoreProviderFactory = EnvTrustStoreProviderFactory;
13057
- exports.EvaluationError = EvaluationError;
13058
- exports.Evaluator = Evaluator;
13059
- exports.ExpressionError = ExpressionError;
13060
13804
  exports.GRANT_PURPOSE_CA_SIGN = GRANT_PURPOSE_CA_SIGN;
13805
+ exports.HTTP_AUTHORIZATION_POLICY_SOURCE_FACTORY_META = FACTORY_META$f;
13806
+ exports.HttpAuthorizationPolicySource = HttpAuthorizationPolicySource;
13807
+ exports.HttpAuthorizationPolicySourceFactory = HttpAuthorizationPolicySourceFactory;
13061
13808
  exports.LOGICALS_OID = LOGICALS_OID;
13062
- exports.LimitExceededError = LimitExceededError;
13063
13809
  exports.NODE_ID_OID = NODE_ID_OID;
13064
13810
  exports.NoAFTSigner = NoAFTSigner;
13065
13811
  exports.NullTrustStoreProvider = NullTrustStoreProvider;
13812
+ exports.PROFILE_NAME_POLICY_HTTP = PROFILE_NAME_POLICY_HTTP;
13066
13813
  exports.PROFILE_NAME_STRICT_OVERLAY = PROFILE_NAME_STRICT_OVERLAY;
13067
- exports.ParseError = ParseError;
13068
- exports.Parser = Parser;
13069
13814
  exports.SID_OID = SID_OID;
13070
13815
  exports.SidOnlyAFTVerifier = SidOnlyAFTVerifier;
13071
13816
  exports.SignedAFTSigner = SignedAFTSigner;
13072
13817
  exports.SignedOptionalAFTVerifier = SignedOptionalAFTVerifier;
13073
13818
  exports.StrictAFTVerifier = StrictAFTVerifier;
13074
13819
  exports.TRUST_STORE_PROVIDER_FACTORY_BASE_TYPE = TRUST_STORE_PROVIDER_FACTORY_BASE_TYPE;
13075
- exports.Tokenizer = Tokenizer;
13076
- exports.TokenizerError = TokenizerError;
13077
13820
  exports.TrustStoreProviderFactory = TrustStoreProviderFactory;
13078
- exports.TypeError = TypeError;
13079
13821
  exports.UnsignedAFTSigner = UnsignedAFTSigner;
13080
13822
  exports.VERSION = VERSION;
13081
13823
  exports.X5CKeyManager = X5CKeyManager;
13082
13824
  exports.X5CKeyManagerFactory = X5CKeyManagerFactory;
13083
13825
  exports.X5C_KEY_MANAGER_FACTORY_META = FACTORY_META$8;
13084
13826
  exports.__advancedSecurityPluginLoader = __advancedSecurityPluginLoader;
13085
- exports.astToString = astToString;
13086
13827
  exports.base64UrlDecode = base64UrlDecode;
13087
13828
  exports.base64UrlEncode = base64UrlEncode;
13088
- exports.calculateAstDepth = calculateAstDepth;
13089
- exports.callBuiltin = callBuiltin;
13090
13829
  exports.channelEncryption = index;
13091
- exports.checkArrayLength = checkArrayLength;
13092
- exports.checkAstDepth = checkAstDepth;
13093
- exports.checkAstNodeCount = checkAstNodeCount;
13094
- exports.checkExpressionLength = checkExpressionLength;
13095
- exports.checkFunctionArgCount = checkFunctionArgCount;
13096
- exports.checkGlobPatternLength = checkGlobPatternLength;
13097
- exports.checkRegexPatternLength = checkRegexPatternLength;
13098
- exports.countAstNodes = countAstNodes;
13099
13830
  exports.createAftHelper = createAftHelper;
13100
13831
  exports.createAftPayload = createAftPayload;
13101
13832
  exports.createAftReplicaStickinessManager = createAftReplicaStickinessManager;
13102
13833
  exports.createAftSigner = createAftSigner;
13103
13834
  exports.createAftVerifier = createAftVerifier;
13104
- exports.createAuthFunctionRegistry = createAuthFunctionRegistry;
13105
13835
  exports.createEd25519Csr = createEd25519Csr;
13106
13836
  exports.createEd25519CsrFromPem = createEd25519CsrFromPem;
13107
13837
  exports.createTestCA = createTestCA;
13108
- exports.evaluate = evaluate;
13109
- exports.evaluateAsBoolean = evaluateAsBoolean;
13110
13838
  exports.extractCertificateInfo = extractCertificateInfo;
13111
13839
  exports.extractLogicalHostsFromCert = extractLogicalHostsFromCert;
13112
13840
  exports.extractNodeIdFromCert = extractNodeIdFromCert;
@@ -13114,17 +13842,12 @@ exports.extractSidFromCert = extractSidFromCert;
13114
13842
  exports.extractSidFromSpiffeId = extractSidFromSpiffeId;
13115
13843
  exports.extractSpiffeIdFromCert = extractSpiffeIdFromCert;
13116
13844
  exports.formatCertificateInfo = formatCertificateInfo;
13117
- exports.getTypeName = getTypeName;
13118
- exports.isBuiltinFunction = isBuiltinFunction;
13119
- exports.normalizeJsValue = normalizeJsValue;
13120
13845
  exports.normalizeStickinessMode = normalizeStickinessMode;
13121
- exports.parse = parse;
13122
13846
  exports.publicKeyFromX5c = publicKeyFromX5c;
13123
13847
  exports.registerAdvancedSecurityFactories = registerAdvancedSecurityFactories;
13124
13848
  exports.sealedEncryption = index$1;
13125
13849
  exports.serializeAftClaims = serializeAftClaims;
13126
13850
  exports.serializeAftHeader = serializeAftHeader;
13127
- exports.tokenize = tokenize;
13128
13851
  exports.utf8Decode = utf8Decode;
13129
13852
  exports.validateJwkX5cCertificate = validateJwkX5cCertificate;
13130
13853
  exports.verifyCertSidIntegrity = verifyCertSidIntegrity;