@noony-serverless/core
Version:
A Middy base framework compatible with Firebase and GCP Cloud Functions with TypeScript
393 lines • 14.4 kB
JavaScript
;
/**
* Guard System Configuration
*
* Comprehensive configuration system for the high-performance guard system.
* Provides type-safe configuration for different deployment environments with
* configurable performance strategies and security policies.
*
* Key Features:
* - Permission resolution strategy configuration (pre-expansion vs on-demand)
* - Cache adapter injection for different environments
* - Performance profiles for development, staging, and production
* - Security policies with conservative cache invalidation
* - Bounded complexity limits for patterns and expressions
*
* @author Noony Framework Team
* @version 1.0.0
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GuardConfiguration = exports.MonitoringLevel = exports.CacheInvalidationStrategy = exports.PermissionResolutionStrategy = void 0;
/**
* Permission resolution strategies for wildcard permissions.
* Determines how wildcard patterns are processed for optimal performance.
*
* @example
* Pre-expansion strategy (production recommended):
* ```typescript
* const productionConfig = {
* permissionResolutionStrategy: PermissionResolutionStrategy.PRE_EXPANSION,
* // Expands "admin.*" to ["admin.users", "admin.reports", "admin.settings"]
* // at user context load time for O(1) runtime checks
* };
* ```
*
* @example
* On-demand strategy (memory efficient):
* ```typescript
* const memoryEfficientConfig = {
* permissionResolutionStrategy: PermissionResolutionStrategy.ON_DEMAND,
* // Matches "admin.*" pattern against user permissions at runtime
* // Lower memory usage but requires pattern matching overhead
* };
* ```
*
* PRE_EXPANSION: Expand wildcards at user context load time
* - Pros: Faster runtime permission checks (O(1) set lookups)
* - Cons: Higher memory usage, requires permission registry
*
* ON_DEMAND: Match wildcards at permission check time
* - Pros: Lower memory usage, supports dynamic permissions
* - Cons: Pattern matching overhead per request
*/
var PermissionResolutionStrategy;
(function (PermissionResolutionStrategy) {
PermissionResolutionStrategy["PRE_EXPANSION"] = "pre-expansion";
PermissionResolutionStrategy["ON_DEMAND"] = "on-demand";
})(PermissionResolutionStrategy || (exports.PermissionResolutionStrategy = PermissionResolutionStrategy = {}));
/**
* Cache invalidation strategies for security
*/
var CacheInvalidationStrategy;
(function (CacheInvalidationStrategy) {
CacheInvalidationStrategy["FLUSH_ALL"] = "flush-all";
CacheInvalidationStrategy["USER_SPECIFIC"] = "user-specific";
})(CacheInvalidationStrategy || (exports.CacheInvalidationStrategy = CacheInvalidationStrategy = {}));
/**
* Performance monitoring levels
*/
var MonitoringLevel;
(function (MonitoringLevel) {
MonitoringLevel["NONE"] = "none";
MonitoringLevel["BASIC"] = "basic";
MonitoringLevel["DETAILED"] = "detailed";
MonitoringLevel["VERBOSE"] = "verbose";
})(MonitoringLevel || (exports.MonitoringLevel = MonitoringLevel = {}));
/**
* GuardConfiguration class implementation.
* Immutable configuration object for the Noony guard system with factory methods
* for creating configurations from environment profiles or predefined templates.
*
* @example
* Create from environment profile:
* ```typescript
* import { GuardConfiguration } from '@noony/core';
*
* const config = GuardConfiguration.fromEnvironmentProfile({
* environment: 'production',
* cacheType: 'redis',
* security: { ... },
* cache: { ... },
* monitoring: { ... }
* });
* ```
*
* @example
* Use predefined configurations:
* ```typescript
* // Development configuration
* const devConfig = GuardConfiguration.development();
*
* // Production configuration
* const prodConfig = GuardConfiguration.production();
*
* // Testing configuration
* const testConfig = GuardConfiguration.testing();
* ```
*
* @example
* Manual configuration:
* ```typescript
* const customConfig = new GuardConfiguration(
* { permissionResolutionStrategy: PermissionResolutionStrategy.PRE_EXPANSION },
* { maxEntries: 10000, defaultTtlMs: 300000 },
* { enablePerformanceTracking: true, logLevel: 'info' }
* );
* ```
*/
class GuardConfiguration {
/**
* Security configuration settings.
* Contains permission resolution strategies and security limits.
*/
security;
/**
* Cache configuration settings.
* Contains cache size limits and TTL values.
*/
cache;
/**
* Monitoring configuration settings.
* Contains logging and metrics collection settings.
*/
monitoring;
/**
* Creates a new GuardConfiguration instance.
*
* @param security - Security configuration settings
* @param cache - Cache configuration settings
* @param monitoring - Monitoring configuration settings
*
* @example
* ```typescript
* const config = new GuardConfiguration(
* {
* permissionResolutionStrategy: PermissionResolutionStrategy.PRE_EXPANSION,
* conservativeCacheInvalidation: true,
* maxExpressionComplexity: 100
* },
* {
* maxEntries: 10000,
* defaultTtlMs: 300000,
* userContextTtlMs: 600000,
* authTokenTtlMs: 900000
* },
* {
* enablePerformanceTracking: true,
* enableDetailedLogging: false,
* logLevel: 'info',
* metricsCollectionInterval: 60000
* }
* );
* ```
*/
constructor(security, cache, monitoring) {
this.security = security;
this.cache = cache;
this.monitoring = monitoring;
}
/**
* Create GuardConfiguration from environment profile.
* Factory method that constructs a configuration from a complete environment profile.
*
* @param profile - Complete environment profile with all configuration sections
* @returns New GuardConfiguration instance
*
* @example
* Create from production profile:
* ```typescript
* const productionProfile: GuardEnvironmentProfile = {
* environment: 'production',
* cacheType: 'redis',
* security: {
* permissionResolutionStrategy: PermissionResolutionStrategy.PRE_EXPANSION,
* conservativeCacheInvalidation: true,
* maxExpressionComplexity: 100
* },
* cache: {
* maxEntries: 50000,
* defaultTtlMs: 600000,
* userContextTtlMs: 1800000,
* authTokenTtlMs: 3600000
* },
* monitoring: {
* enablePerformanceTracking: true,
* enableDetailedLogging: false,
* logLevel: 'error',
* metricsCollectionInterval: 60000
* }
* };
*
* const config = GuardConfiguration.fromEnvironmentProfile(productionProfile);
* ```
*/
static fromEnvironmentProfile(profile) {
return new GuardConfiguration(profile.security, profile.cache, profile.monitoring);
}
/**
* Create default development configuration.
* Pre-configured settings optimized for development environments with fast refresh
* and detailed logging for debugging.
*
* @returns GuardConfiguration optimized for development
*
* @example
* ```typescript
* const devConfig = GuardConfiguration.development();
*
* // Configuration includes:
* // - On-demand permission resolution (lower memory, dynamic)
* // - Conservative cache invalidation disabled (faster refresh)
* // - Lower complexity limits for faster feedback
* // - Shorter TTL values for rapid development cycles
* // - Detailed logging and debug level
* // - Frequent metrics collection (30 seconds)
* ```
*/
static development() {
return new GuardConfiguration({
permissionResolutionStrategy: PermissionResolutionStrategy.ON_DEMAND,
conservativeCacheInvalidation: false,
maxExpressionComplexity: 50,
maxPatternDepth: 3,
maxNestingDepth: 2,
}, {
maxEntries: 500,
defaultTtlMs: 5 * 60 * 1000, // 5 minutes
userContextTtlMs: 2 * 60 * 1000, // 2 minutes
authTokenTtlMs: 2 * 60 * 1000, // 2 minutes
}, {
enablePerformanceTracking: true,
enableDetailedLogging: true,
logLevel: 'debug',
metricsCollectionInterval: 30000, // 30 seconds
});
}
/**
* Create default production configuration.
* Pre-configured settings optimized for production environments with high performance,
* security, and stability.
*
* @returns GuardConfiguration optimized for production
*
* @example
* ```typescript
* const prodConfig = GuardConfiguration.production();
*
* // Configuration includes:
* // - Pre-expansion permission resolution (high performance)
* // - Conservative cache invalidation enabled (high security)
* // - Higher complexity limits for production workloads
* // - Longer TTL values for better performance
* // - Performance tracking enabled, detailed logging disabled
* // - Standard metrics collection (1 minute intervals)
* ```
*/
static production() {
return new GuardConfiguration({
permissionResolutionStrategy: PermissionResolutionStrategy.PRE_EXPANSION,
conservativeCacheInvalidation: true,
maxExpressionComplexity: 100,
maxPatternDepth: 3,
maxNestingDepth: 2,
}, {
maxEntries: 2000,
defaultTtlMs: 15 * 60 * 1000, // 15 minutes
userContextTtlMs: 10 * 60 * 1000, // 10 minutes
authTokenTtlMs: 5 * 60 * 1000, // 5 minutes
}, {
enablePerformanceTracking: true,
enableDetailedLogging: false,
logLevel: 'info',
metricsCollectionInterval: 60000, // 1 minute
});
}
/**
* Validate configuration settings.
* Ensures all configuration values are within acceptable bounds and constraints
* to prevent security vulnerabilities and performance issues.
*
* @throws Error if any configuration value is invalid
*
* @example
* ```typescript
* const config = new GuardConfiguration(securityConfig, cacheConfig, monitoringConfig);
*
* try {
* config.validate();
* console.log('Configuration is valid');
* } catch (error) {
* console.error('Invalid configuration:', error.message);
* // Handle configuration error
* }
* ```
*
* @example
* Validation constraints:
* ```typescript
* // These will throw validation errors:
* // maxPatternDepth must be 2 or 3 (prevents deep recursion)
* // maxNestingDepth must be 2 (prevents complex expressions)
* // maxExpressionComplexity must be positive
* // defaultTtlMs must be at least 1000ms (1 second)
* ```
*/
/**
* Check if caching is enabled via environment variable.
*
* Caching is disabled by default for security-first approach.
* Only enabled when NOONY_GUARD_CACHE_ENABLE is explicitly set to 'true'.
*
* @returns true if caching should be enabled, false otherwise
*
* @example
* ```typescript
* // Caching disabled (default)
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
* console.log(GuardConfiguration.isCachingEnabled()); // false
*
* // Caching enabled
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
* console.log(GuardConfiguration.isCachingEnabled()); // true
*
* // Caching disabled (any other value)
* process.env.NOONY_GUARD_CACHE_ENABLE = 'false';
* console.log(GuardConfiguration.isCachingEnabled()); // false
* ```
*/
static isCachingEnabled() {
return process.env.NOONY_GUARD_CACHE_ENABLE === 'true';
}
/**
* Get effective cache type considering environment variable override.
*
* Environment variable takes precedence for security:
* - If NOONY_GUARD_CACHE_ENABLE is not 'true', returns 'none'
* - Otherwise returns the specified cacheType
*
* @param cacheType - Configured cache type
* @returns Effective cache type after environment variable consideration
*
* @example
* ```typescript
* // Environment variable not set - caching disabled
* process.env.NOONY_GUARD_CACHE_ENABLE = undefined;
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'none'
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'none'
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
*
* // Environment variable enabled - respect cacheType
* process.env.NOONY_GUARD_CACHE_ENABLE = 'true';
* console.log(GuardConfiguration.getEffectiveCacheType('memory')); // 'memory'
* console.log(GuardConfiguration.getEffectiveCacheType('redis')); // 'redis'
* console.log(GuardConfiguration.getEffectiveCacheType('none')); // 'none'
* ```
*/
static getEffectiveCacheType(cacheType) {
// If caching is disabled by environment variable, always return 'none'
if (!GuardConfiguration.isCachingEnabled()) {
return 'none';
}
// Otherwise return the specified cache type
return cacheType;
}
validate() {
if (this.security.maxPatternDepth !== undefined &&
(this.security.maxPatternDepth < 2 || this.security.maxPatternDepth > 3)) {
throw new Error('maxPatternDepth must be 2 or 3');
}
if (this.security.maxNestingDepth !== undefined &&
this.security.maxNestingDepth !== 2) {
throw new Error('maxNestingDepth must be 2');
}
if (this.security.maxExpressionComplexity !== undefined &&
this.security.maxExpressionComplexity < 1) {
throw new Error('maxExpressionComplexity must be positive');
}
if (this.cache.defaultTtlMs < 1000) {
throw new Error('defaultTtlMs must be at least 1 second');
}
}
}
exports.GuardConfiguration = GuardConfiguration;
//# sourceMappingURL=GuardConfiguration.js.map