@dollhousemcp/mcp-server
Version:
DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.
344 lines • 45.6 kB
JavaScript
/**
* Constants for Ensemble elements
*
* Defines limits, defaults, and security constants following patterns from other elements
*
* CONFIGURABILITY (Issue #368):
* Limits can be configured via:
* 1. Environment variables (e.g., ENSEMBLE_MAX_ELEMENTS=100)
* 2. Global configuration object (setGlobalEnsembleLimits())
* 3. Per-ensemble overrides via metadata.resourceLimits
*
* Priority: Per-ensemble > Global config > Environment variables > Defaults
*
* @example
* // 1. Environment variables (set before server starts)
* // ENSEMBLE_MAX_ELEMENTS=100
* // ENSEMBLE_MAX_NESTING_DEPTH=3
* // ENSEMBLE_MAX_ACTIVATION_TIME=60000
*
* @example
* // 2. Global configuration (programmatic)
* import { setGlobalEnsembleLimits } from './constants.js';
* setGlobalEnsembleLimits({
* maxElements: 75,
* maxNestingDepth: 4,
* maxActivationTime: 45000
* });
*
* @example
* // 3. Per-ensemble override (in ensemble metadata)
* const ensemble = new Ensemble({
* name: 'my-ensemble',
* resourceLimits: {
* maxActiveElements: 25, // Maps to MAX_ELEMENTS
* maxExecutionTimeMs: 10000 // Maps to MAX_ACTIVATION_TIME
* }
* }, elements, metadataService);
*/
import { logger } from '../../utils/logger.js';
import { parseEnvInt } from '../../config/env-utils.js';
// ==================== HARD LIMITS (Security) ====================
/**
* Absolute maximum values for security - cannot be exceeded even with configuration
* These prevent resource exhaustion and DoS attacks
*/
export const ENSEMBLE_HARD_LIMITS = {
MAX_ELEMENTS: 500, // Absolute max elements (security ceiling)
MAX_NESTING_DEPTH: 10, // Absolute max nesting (prevent stack overflow)
MAX_ACTIVATION_TIME: 300000, // 5 minutes absolute max (300 seconds)
MAX_CONTEXT_SIZE: 10000, // Absolute max context keys
MAX_CONTEXT_VALUE_SIZE: 1048576, // 1MB absolute max per value
MAX_DEPENDENCIES: 50, // Absolute max dependencies per element
MAX_CONDITION_LENGTH: 1000 // Absolute max condition length
};
/**
* Minimum values for safety - configured values cannot go below these
*/
export const ENSEMBLE_MIN_LIMITS = {
MAX_ELEMENTS: 1, // Must allow at least 1 element
MAX_NESTING_DEPTH: 0, // 0 means no nesting allowed
MAX_ACTIVATION_TIME: 1000, // At least 1 second
MAX_CONTEXT_SIZE: 10, // At least 10 context keys
MAX_CONTEXT_VALUE_SIZE: 100, // At least 100 bytes per value
MAX_DEPENDENCIES: 1, // At least 1 dependency allowed
MAX_CONDITION_LENGTH: 10 // At least 10 chars for conditions
};
// Global configuration storage (module-level singleton)
let globalConfig = {};
/**
* Set global ensemble limits configuration
* Values are validated against hard limits
*
* @param config - Configuration object with desired limits
* @example
* setGlobalEnsembleLimits({
* maxElements: 100,
* maxNestingDepth: 3,
* maxActivationTime: 60000
* });
*/
export function setGlobalEnsembleLimits(config) {
const previousConfig = { ...globalConfig };
const previousKeys = Object.keys(previousConfig);
globalConfig = { ...config };
const newKeys = Object.keys(config);
// Determine what changed for the audit trail
const addedKeys = newKeys.filter(k => !previousKeys.includes(k));
const removedKeys = previousKeys.filter(k => !newKeys.includes(k));
const modifiedKeys = newKeys.filter(k => previousKeys.includes(k) &&
previousConfig[k] !== config[k]);
const timestamp = new Date().toISOString();
const summary = `${addedKeys.length} added, ${removedKeys.length} removed, ${modifiedKeys.length} modified`;
// Info level: concise summary for normal operation
logger.info('Global ensemble limits configuration updated', {
timestamp,
summary,
configuredKeys: newKeys
});
// Debug level: complete audit trail for troubleshooting
logger.debug('Global ensemble limits configuration audit trail', {
timestamp,
previousConfig: previousKeys.length > 0 ? previousConfig : '(no previous configuration)',
newConfig: config,
changes: {
added: addedKeys.length > 0 ? addedKeys : undefined,
removed: removedKeys.length > 0 ? removedKeys : undefined,
modified: modifiedKeys.length > 0 ? modifiedKeys.map(k => ({
key: k,
from: previousConfig[k],
to: config[k]
})) : undefined
},
summary,
impact: 'New limits apply to ensembles created or activated after this change. Existing cached limits are not affected until invalidateLimitsCache() is called.'
});
}
/**
* Get current global ensemble limits configuration
* @returns Copy of current global config
*/
export function getGlobalEnsembleLimits() {
return { ...globalConfig };
}
/**
* Reset global ensemble limits to defaults (clears all overrides)
*/
export function resetGlobalEnsembleLimits() {
const previousConfig = { ...globalConfig };
const hadPreviousConfig = Object.keys(previousConfig).length > 0;
globalConfig = {};
const timestamp = new Date().toISOString();
const clearedKeys = hadPreviousConfig ? Object.keys(previousConfig) : [];
// Info level: concise summary for normal operation
logger.info('Global ensemble limits configuration reset to defaults', {
timestamp,
clearedCount: clearedKeys.length
});
// Debug level: complete audit trail for troubleshooting
if (hadPreviousConfig) {
logger.debug('Global ensemble limits reset audit trail', {
timestamp,
previousConfig,
clearedKeys,
newConfig: '(using defaults - environment variables and per-ensemble overrides still apply)',
impact: 'Ensembles will now use environment variables or built-in defaults. Existing cached limits are not affected until invalidateLimitsCache() is called.'
});
}
}
/**
* Get effective limits with proper priority:
* Per-ensemble override > Global config > Environment variable > Default
*
* @param perEnsembleOverrides - Optional per-ensemble limit overrides
* @returns Resolved limits object
*/
export function getEffectiveLimits(perEnsembleOverrides) {
// Helper to resolve a single limit value
const resolveLimit = (key, envVar, defaultVal, minVal, maxVal) => {
// Priority: per-ensemble > global > env > default
let value = defaultVal;
// Check environment variable
const envValue = parseEnvInt(envVar, defaultVal, minVal, maxVal, 'Ensemble limit');
if (process.env[envVar] !== undefined) {
value = envValue;
}
// Check global config
if (globalConfig[key] !== undefined) {
value = Math.max(minVal, Math.min(maxVal, globalConfig[key]));
}
// Check per-ensemble override
if (perEnsembleOverrides?.[key] !== undefined) {
value = Math.max(minVal, Math.min(maxVal, perEnsembleOverrides[key]));
}
return value;
};
return {
MAX_ELEMENTS: resolveLimit('maxElements', 'ENSEMBLE_MAX_ELEMENTS', 50, ENSEMBLE_MIN_LIMITS.MAX_ELEMENTS, ENSEMBLE_HARD_LIMITS.MAX_ELEMENTS),
MAX_NESTING_DEPTH: resolveLimit('maxNestingDepth', 'ENSEMBLE_MAX_NESTING_DEPTH', 5, ENSEMBLE_MIN_LIMITS.MAX_NESTING_DEPTH, ENSEMBLE_HARD_LIMITS.MAX_NESTING_DEPTH),
MAX_ACTIVATION_TIME: resolveLimit('maxActivationTime', 'ENSEMBLE_MAX_ACTIVATION_TIME', 30000, ENSEMBLE_MIN_LIMITS.MAX_ACTIVATION_TIME, ENSEMBLE_HARD_LIMITS.MAX_ACTIVATION_TIME),
MAX_CONTEXT_SIZE: resolveLimit('maxContextSize', 'ENSEMBLE_MAX_CONTEXT_SIZE', 1000, ENSEMBLE_MIN_LIMITS.MAX_CONTEXT_SIZE, ENSEMBLE_HARD_LIMITS.MAX_CONTEXT_SIZE),
MAX_CONTEXT_VALUE_SIZE: resolveLimit('maxContextValueSize', 'ENSEMBLE_MAX_CONTEXT_VALUE_SIZE', 10000, ENSEMBLE_MIN_LIMITS.MAX_CONTEXT_VALUE_SIZE, ENSEMBLE_HARD_LIMITS.MAX_CONTEXT_VALUE_SIZE),
MAX_DEPENDENCIES: resolveLimit('maxDependencies', 'ENSEMBLE_MAX_DEPENDENCIES', 10, ENSEMBLE_MIN_LIMITS.MAX_DEPENDENCIES, ENSEMBLE_HARD_LIMITS.MAX_DEPENDENCIES),
MAX_CONDITION_LENGTH: resolveLimit('maxConditionLength', 'ENSEMBLE_MAX_CONDITION_LENGTH', 200, ENSEMBLE_MIN_LIMITS.MAX_CONDITION_LENGTH, ENSEMBLE_HARD_LIMITS.MAX_CONDITION_LENGTH)
};
}
// ==================== DEFAULT LIMITS (Backwards Compatible) ====================
/**
* Resource limits to prevent DoS attacks and ensure system stability
*
* Note: Rate limiting is not implemented at the Ensemble level because:
* 1. The activationInProgress flag already prevents concurrent activations
* 2. Rate limiting should be handled at the handler/API level, not in the domain model
* 3. Different deployment scenarios may have different rate limiting requirements
*
* CONFIGURABILITY: Use getEffectiveLimits() to get limits that respect
* environment variables, global config, and per-ensemble overrides.
* This constant provides the base defaults for backwards compatibility.
*/
export const ENSEMBLE_LIMITS = {
MAX_ELEMENTS: 50, // Maximum elements in an ensemble
MAX_NESTING_DEPTH: 5, // Maximum depth of nested ensembles
MAX_ACTIVATION_TIME: 30000, // 30 seconds max activation time
MAX_CONTEXT_SIZE: 1000, // Maximum keys in shared context
MAX_CONTEXT_VALUE_SIZE: 10000, // Maximum size of a context value (bytes)
MAX_DEPENDENCIES: 10, // Maximum dependencies per element
MAX_CONDITION_LENGTH: 200 // Maximum length of activation condition
};
/**
* Default values for ensemble configuration
*/
export const ENSEMBLE_DEFAULTS = {
ACTIVATION_STRATEGY: 'sequential',
CONFLICT_RESOLUTION: 'last-write',
ELEMENT_ROLE: 'support',
PRIORITY: 50, // Mid-range priority (0-100)
ALLOW_NESTED: true,
ACTIVATION_TIMEOUT: 5000, // 5 seconds per element
MAX_NESTING_DEPTH: 5,
CONTEXT_SHARING: 'selective'
};
/**
* Supported activation strategies
* Must match ActivationStrategy type in types.ts
*/
export const ACTIVATION_STRATEGIES = [
'all',
'sequential',
'lazy',
'conditional',
'priority'
];
/**
* Supported conflict resolution strategies
*/
export const CONFLICT_STRATEGIES = [
'last-write',
'first-write',
'priority',
'merge',
'error'
];
/**
* Element roles within an ensemble
*/
export const ELEMENT_ROLES = [
'primary',
'support',
'override',
'monitor',
'core' // Legacy alias for 'primary' — accepted for backwards compatibility
];
/**
* Activation modes for elements
*/
export const ACTIVATION_MODES = [
'always',
'on-demand',
'conditional'
];
/**
* Security event types for ensemble operations
* These are logged via SecurityMonitor for audit trails
*/
export const ENSEMBLE_SECURITY_EVENTS = {
CIRCULAR_DEPENDENCY: 'ENSEMBLE_CIRCULAR_DEPENDENCY',
RESOURCE_LIMIT_EXCEEDED: 'ENSEMBLE_RESOURCE_LIMIT_EXCEEDED',
ACTIVATION_TIMEOUT: 'ENSEMBLE_ACTIVATION_TIMEOUT',
ACTIVATION_FAILED: 'ENSEMBLE_ACTIVATION_FAILED',
SUSPICIOUS_CONDITION: 'ENSEMBLE_SUSPICIOUS_CONDITION',
CONDITION_EVALUATION_FAILED: 'ENSEMBLE_CONDITION_EVALUATION_FAILED',
NESTED_DEPTH_EXCEEDED: 'ENSEMBLE_NESTED_DEPTH_EXCEEDED',
CONTEXT_SIZE_EXCEEDED: 'ENSEMBLE_CONTEXT_SIZE_EXCEEDED',
CONTEXT_VALUE_TOO_LARGE: 'ENSEMBLE_CONTEXT_VALUE_TOO_LARGE',
SAVED: 'ENSEMBLE_SAVED',
IMPORTED: 'ENSEMBLE_IMPORTED',
DELETED: 'ENSEMBLE_DELETED',
ACTIVATED: 'ENSEMBLE_ACTIVATED',
DEACTIVATED: 'ENSEMBLE_DEACTIVATED'
};
/**
* Error messages for validation
*/
export const ENSEMBLE_ERRORS = {
TOO_MANY_ELEMENTS: `Ensemble cannot contain more than ${ENSEMBLE_LIMITS.MAX_ELEMENTS} elements`,
NESTING_TOO_DEEP: `Ensemble nesting depth cannot exceed ${ENSEMBLE_LIMITS.MAX_NESTING_DEPTH}`,
CIRCULAR_DEPENDENCY: 'Circular dependency detected in ensemble',
INVALID_STRATEGY: 'Invalid activation strategy',
INVALID_CONFLICT_RESOLUTION: 'Invalid conflict resolution strategy',
INVALID_ELEMENT_ROLE: 'Invalid element role',
INVALID_ACTIVATION_MODE: 'Invalid activation mode',
ELEMENT_NOT_FOUND: 'Element not found in ensemble',
ACTIVATION_TIMEOUT: 'Ensemble activation timed out',
CONTEXT_OVERFLOW: 'Shared context size exceeded limits',
ELEMENT_LOAD_FAILED: 'Failed to load element',
CONDITION_EVALUATION_FAILED: 'Failed to evaluate activation condition'
};
/**
* Regex patterns for validation
*/
export const ENSEMBLE_PATTERNS = {
// Condition pattern - allows safe comparison expressions
// Allows almost any character EXCEPT obviously dangerous ones (backticks, $, braces)
// The real security enforcement happens in:
// 1. DANGEROUS_CONDITION_PATTERNS check (blocks eval, require, etc.)
// 2. VM sandbox execution (prevents code injection)
//
// This pattern just prevents template literals (`), variable interpolation (${}),
// and code blocks ({}). Everything else is allowed and will be safely evaluated in the VM.
CONDITION_PATTERN: /^[^`${}]+$/,
// Element name pattern (alphanumeric, hyphens, underscores)
ELEMENT_NAME_PATTERN: /^[a-zA-Z0-9_-]+$/
};
/**
* Dangerous keywords that should be rejected in conditions
*
* These patterns are checked separately from CONDITION_PATTERN for security.
* Note: We focus on dangerous code execution patterns rather than unsupported
* operators, since condition evaluation isn't implemented yet. When it is
* implemented, the evaluator will handle operator support properly.
*/
export const DANGEROUS_CONDITION_PATTERNS = [
// Function calls and code execution
/\beval\b/i,
/\bFunction\b/i,
/\brequire\b/i,
/\bimport\b/i,
/\bexport\b/i,
// Process and global access
/\bprocess\b/i,
/\bglobal\b/i,
/\bwindow\b/i,
/\bdocument\b/i,
// Prototype pollution
/__proto__/i,
/\bconstructor\b/i,
/\.prototype\b/i,
// Dangerous operators
/[;,?:]/, // Semicolon, comma, ternary
/(?<![=!<>])=(?![=])/, // Assignment (but allow ==, !=, ===, !==, <=, >=)
/\+=|-=|\*=|\/=|%=/, // Compound assignment
// Empty or whitespace only
/^\s*$/
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2VsZW1lbnRzL2Vuc2VtYmxlcy9jb25zdGFudHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQ0c7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRXhELG1FQUFtRTtBQUNuRTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRztJQUNsQyxZQUFZLEVBQUUsR0FBRyxFQUFvQiwyQ0FBMkM7SUFDaEYsaUJBQWlCLEVBQUUsRUFBRSxFQUFnQixnREFBZ0Q7SUFDckYsbUJBQW1CLEVBQUUsTUFBTSxFQUFVLHVDQUF1QztJQUM1RSxnQkFBZ0IsRUFBRSxLQUFLLEVBQWMsNEJBQTRCO0lBQ2pFLHNCQUFzQixFQUFFLE9BQU8sRUFBTSw2QkFBNkI7SUFDbEUsZ0JBQWdCLEVBQUUsRUFBRSxFQUFpQix3Q0FBd0M7SUFDN0Usb0JBQW9CLEVBQUUsSUFBSSxDQUFXLGdDQUFnQztDQUM3RCxDQUFDO0FBRVg7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRztJQUNqQyxZQUFZLEVBQUUsQ0FBQyxFQUFzQixnQ0FBZ0M7SUFDckUsaUJBQWlCLEVBQUUsQ0FBQyxFQUFpQiw2QkFBNkI7SUFDbEUsbUJBQW1CLEVBQUUsSUFBSSxFQUFZLG9CQUFvQjtJQUN6RCxnQkFBZ0IsRUFBRSxFQUFFLEVBQWlCLDJCQUEyQjtJQUNoRSxzQkFBc0IsRUFBRSxHQUFHLEVBQVUsK0JBQStCO0lBQ3BFLGdCQUFnQixFQUFFLENBQUMsRUFBa0IsZ0NBQWdDO0lBQ3JFLG9CQUFvQixFQUFFLEVBQUUsQ0FBYSxtQ0FBbUM7Q0FDaEUsQ0FBQztBQXdCWCx3REFBd0Q7QUFDeEQs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LEVBQUUsMENBQTBDO0lBQy9ELGdCQUFnQixFQUFFLDZCQUE2QjtJQUMvQywyQkFBMkIsRUFBRSxzQ0FBc0M7SUFDbkUsb0JBQW9CLEVBQUUsc0JBQXNCO0lBQzVDLHVCQUF1QixFQUFFLHlCQUF5QjtJQUNsRCxpQkFBaUIsRUFBRSwrQkFBK0I7SUFDbEQsa0JBQWtCLEVBQUUsK0JBQStCO0lBQ25ELGdCQUFnQixFQUFFLHFDQUFxQztJQUN2RCxtQkFBbUIsRUFBRSx3QkFBd0I7SUFDN0MsMkJBQTJCLEVBQUUseUNBQXlDO0NBQzlELENBQUM7QUFFWDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHO0lBQy9CLHlEQUF5RDtJQUN6RCxxRkFBcUY7SUFDckYsNENBQTRDO0lBQzVDLHFFQUFxRTtJQUNyRSxvREFBb0Q7SUFDcEQsRUFBRTtJQUNGLGtGQUFrRjtJQUNsRiwyRkFBMkY7SUFDM0YsaUJBQWlCLEVBQUUsWUFBWTtJQUUvQiw0REFBNEQ7SUFDNUQsb0JBQW9CLEVBQUUsa0JBQWtCO0NBQ2hDLENBQUM7QUFFWDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUc7SUFDMUMsb0NBQW9DO0lBQ3BDLFdBQVc7SUFDWCxlQUFlO0lBQ2YsY0FBYztJQUNkLGFBQWE7SUFDYixhQUFhO0lBRWIsNEJBQTRCO0lBQzVCLGNBQWM7SUFDZCxhQUFhO0lBQ2IsYUFBYTtJQUNiLGVBQWU7SUFFZixzQkFBc0I7SUFDdEIsWUFBWTtJQUNaLGtCQUFrQjtJQUNsQixnQkFBZ0I7SUFFaEIsc0JBQXNCO0lBQ3RCLFFBQVEsRUFBcUIsNEJBQTRCO0lBQ3pELHFCQUFxQixFQUFRLGtEQUFrRDtJQUMvRSxtQkFBbUIsRUFBVSxzQkFBc0I7SUFFbkQsMkJBQTJCO0lBQzNCLE9BQU87Q0FDQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb25zdGFudHMgZm9yIEVuc2VtYmxlIGVsZW1lbnRzXG4gKlxuICogRGVmaW5lcyBsaW1pdHMsIGRlZmF1bHRzLCBhbmQgc2VjdXJpdHkgY29uc3RhbnRzIGZvbGxvd2luZyBwYXR0ZXJucyBmcm9tIG90aGVyIGVsZW1lbnRzXG4gKlxuICogQ09ORklHVVJBQklMSVRZIChJc3N1ZSAjMzY4KTpcbiAqIExpbWl0cyBjYW4gYmUgY29uZmlndXJlZCB2aWE6XG4gKiAxLiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgKGUuZy4sIEVOU0VNQkxFX01BWF9FTEVNRU5UUz0xMDApXG4gKiAyLiBHbG9iYWwgY29uZmlndXJhdGlvbiBvYmplY3QgKHNldEdsb2JhbEVuc2VtYmxlTGltaXRzKCkpXG4gKiAzLiBQZXItZW5zZW1ibGUgb3ZlcnJpZGVzIHZpYSBtZXRhZGF0YS5yZXNvdXJjZUxpbWl0c1xuICpcbiAqIFByaW9yaXR5OiBQZXItZW5zZW1ibGUgPiBHbG9iYWwgY29uZmlnID4gRW52aXJvbm1lbnQgdmFyaWFibGVzID4gRGVmYXVsdHNcbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gMS4gRW52aXJvbm1lbnQgdmFyaWFibGVzIChzZXQgYmVmb3JlIHNlcnZlciBzdGFydHMpXG4gKiAvLyBFTlNFTUJMRV9NQVhfRUxFTUVOVFM9MTAwXG4gKiAvLyBFTlNFTUJMRV9NQVhfTkVTVElOR19ERVBUSD0zXG4gKiAvLyBFTlNFTUJMRV9NQVhfQUNUSVZBVElPTl9USU1FPTYwMDAwXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIDIuIEdsb2JhbCBjb25maWd1cmF0aW9uIChwcm9ncmFtbWF0aWMpXG4gKiBpbXBvcnQgeyBzZXRHbG9iYWxFbnNlbWJsZUxpbWl0cyB9IGZyb20gJy4vY29uc3RhbnRzLmpzJztcbiAqIHNldEdsb2JhbEVuc2VtYmxlTGltaXRzKHtcbiAqICAgbWF4RWxlbWVudHM6IDc1LFxuICogICBtYXhOZXN0aW5nRGVwdGg6IDQsXG4gKiAgIG1heEFjdGl2YXRpb25UaW1lOiA0NTAwMFxuICogfSk7XG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIDMuIFBlci1lbnNlbWJsZSBvdmVycmlkZSAoaW4gZW5zZW1ibGUgbWV0YWRhdGEpXG4gKiBjb25zdCBlbnNlbWJsZSA9IG5ldyBFbnNlbWJsZSh7XG4gKiAgIG5hbWU6ICdteS1lbnNlbWJsZScsXG4gKiAgIHJlc291cmNlTGltaXRzOiB7XG4gKiAgICAgbWF4QWN0aXZlRWxlbWVudHM6IDI1LCAgICAgIC8vIE1hcHMgdG8gTUFYX0VMRU1FTlRTXG4gKiAgICAgbWF4RXhlY3V0aW9uVGltZU1zOiAxMDAwMCAgIC8vIE1hcHMgdG8gTUFYX0FDVElWQVRJT05fVElNRVxuICogICB9XG4gKiB9LCBlbGVtZW50cywgbWV0YWRhdGFTZXJ2aWNlKTtcbiAqL1xuXG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tICcuLi8uLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgcGFyc2VFbnZJbnQgfSBmcm9tICcuLi8uLi9jb25maWcvZW52LXV0aWxzLmpzJztcblxuLy8gPT09PT09PT09PT09PT09PT09PT0gSEFSRCBMSU1JVFMgKFNlY3VyaXR5KSA9PT09PT09PT09PT09PT09PT09PVxuLyoqXG4gKiBBYnNvbHV0ZSBtYXhpbXVtIHZhbHVlcyBmb3Igc2VjdXJpdHkgLSBjYW5ub3QgYmUgZXhjZWVkZWQgZXZlbiB3aXRoIGNvbmZpZ3VyYXRpb25cbiAqIFRoZXNlIHByZXZlbnQgcmVzb3VyY2UgZXhoYXVzdGlvbiBhbmQgRG9TIGF0dGFja3NcbiAqL1xuZXhwb3J0IGNvbnN0IEVOU0VNQkxFX0hBUkRfTElNSVRTID0ge1xuICBNQVhfRUxFTUVOVFM6IDUwMCwgICAgICAgICAgICAgICAgICAgLy8gQWJzb2x1dGUgbWF4IGVsZW1lbnRzIChzZWN1cml0eSBjZWlsaW5nKVxuICBNQVhfTkVTVElOR19ERVBUSDogMTAsICAgICAgICAgICAgICAgLy8gQWJzb2x1dGUgbWF4IG5lc3RpbmcgKHByZXZlbnQgc3RhY2sgb3ZlcmZsb3cpXG4gIE1BWF9BQ1RJVkFUSU9OX1RJTUU6IDMwMDAwMCwgICAgICAgICAvLyA1IG1pbnV0ZXMgYWJzb2x1dGUgbWF4ICgzMDAgc2Vjb25kcylcbiAgTUFYX0NPTlRFWFRfU0laRTogMTAwMDAsICAgICAgICAgICAgIC8vIEFic29sdXRlIG1heCBjb250ZXh0IGtleXNcbiAgTUFYX0NPTlRFWFRfVkFMVUVfU0laRTogMTA0ODU3NiwgICAgIC8vIDFNQiBhYnNvbHV0ZSBtYXggcGVyIHZhbHVlXG4gIE1BWF9ERVBFTkRFTkNJRVM6IDUwLCAgICAgICAgICAgICAgICAvLyBBYnNvbHV0ZSBtYXggZGVwZW5kZW5jaWVzIHBlciBlbGVtZW50XG4gIE1BWF9DT05ESVRJT05fTEVOR1RIOiAxMDAwICAgICAgICAgICAvLyBBYnNvbHV0ZSBtYXggY29uZGl0aW9uIGxlbmd0aFxufSBhcyBjb25zdDtcblxuLyoqXG4gKiBNaW5pbXVtIHZhbHVlcyBmb3Igc2FmZXR5IC0gY29uZmlndXJlZCB2YWx1ZXMgY2Fubm90IGdvIGJlbG93IHRoZXNlXG4gKi9cbmV4cG9ydCBjb25zdCBFTlNFTUJMRV9NSU5fTElNSVRTID0ge1xuICBNQVhfRUxFTUVOVFM6IDEsICAgICAgICAgICAgICAgICAgICAgLy8gTXVzdCBhbGxvdyBhdCBsZWFzdCAxIGVsZW1lbnRcbiAgTUFYX05FU1RJTkdfREVQVEg6IDAsICAgICAgICAgICAgICAgIC8vIDAgbWVhbnMgbm8gbmVzdGluZyBhbGxvd2VkXG4gIE1BWF9BQ1RJVkFUSU9OX1RJTUU6IDEwMDAsICAgICAgICAgICAvLyBBdCBsZWFzdCAxIHNlY29uZFxuICBNQVhfQ09OVEVYVF9TSVpFOiAxMCwgICAgICAgICAgICAgICAgLy8gQXQgbGVhc3QgMTAgY29udGV4dCBrZXlzXG4gIE1BWF9DT05URVhUX1ZBTFVFX1NJWkU6IDEwMCwgICAgICAgICAvLyBBdCBsZWFzdCAxMDAgYnl0ZXMgcGVyIHZhbHVlXG4gIE1BWF9ERVBFTkRFTkNJRVM6IDEsICAgICAgICAgICAgICAgICAvLyBBdCBsZWFzdCAxIGRlcGVuZGVuY3kgYWxsb3dlZFxuICBNQVhfQ09ORElUSU9OX0xFTkdUSDogMTAgICAgICAgICAgICAgLy8gQXQgbGVhc3QgMTAgY2hhcnMgZm9yIGNvbmRpdGlvbnNcbn0gYXMgY29uc3Q7XG5cbi8vID09PT09PT09PT09PT09PT09PT09IEdMT0JBTCBDT05GSUdVUkFUSU9OID09PT09PT09PT09PT09PT09PT09XG4vKipcbiAqIEludGVyZmFjZSBmb3IgY29uZmlndXJhYmxlIGVuc2VtYmxlIGxpbWl0c1xuICogQWxsIHByb3BlcnRpZXMgYXJlIG9wdGlvbmFsIC0gdW5zZXQgcHJvcGVydGllcyB1c2UgZGVmYXVsdHNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnNlbWJsZUxpbWl0c0NvbmZpZyB7XG4gIC8qKiBNYXhpbXVtIGVsZW1lbnRzIGluIGFuIGVuc2VtYmxlIChkZWZhdWx0OiA1MCwgbWF4OiA1MDApICovXG4gIG1heEVsZW1lbnRzPzogbnVtYmVyO1xuICAvKiogTWF4aW11bSBkZXB0aCBvZiBuZXN0ZWQgZW5zZW1ibGVzIChkZWZhdWx0OiA1LCBtYXg6IDEwKSAqL1xuICBtYXhOZXN0aW5nRGVwdGg/OiBudW1iZXI7XG4gIC8qKiBNYXhpbXVtIGFjdGl2YXRpb24gdGltZSBpbiBtcyAoZGVmYXVsdDogMzAwMDAsIG1heDogMzAwMDAwKSAqL1xuICBtYXhBY3RpdmF0aW9uVGltZT86IG51bWJlcjtcbiAgLyoqIE1heGltdW0ga2V5cyBpbiBzaGFyZWQgY29udGV4dCAoZGVmYXVsdDogMTAwMCwgbWF4OiAxMDAwMCkgKi9cbiAgbWF4Q29udGV4dFNpemU/OiBudW1iZXI7XG4gIC8qKiBNYXhpbXVtIHNpemUgb2YgYSBjb250ZXh0IHZhbHVlIGluIGJ5dGVzIChkZWZhdWx0OiAxMDAwMCwgbWF4OiAxMDQ4NTc2KSAqL1xuICBtYXhDb250ZXh0VmFsdWVTaXplPzogbnVtYmVyO1xuICAvKiogTWF4aW11bSBkZXBlbmRlbmNpZXMgcGVyIGVsZW1lbnQgKGRlZmF1bHQ6IDEwLCBtYXg6IDUwKSAqL1xuICBtYXhEZXBlbmRlbmNpZXM/OiBudW1iZXI7XG4gIC8qKiBNYXhpbXVtIGxlbmd0aCBvZiBhY3RpdmF0aW9uIGNvbmRpdGlvbiAoZGVmYXVsdDogMjAwLCBtYXg6IDEwMDApICovXG4gIG1heENvbmRpdGlvbkxlbmd0aD86IG51bWJlcjtcbn1cblxuLy8gR2xvYmFsIGNvbmZpZ3VyYXRpb24gc3RvcmFnZSAobW9kdWxlLWxldmVsIHNpbmdsZXRvbilcbmxldCBnbG9iYWxDb25maWc6IEVuc2VtYmxlTGltaXRzQ29uZmlnID0ge307XG5cbi8qKlxuICogU2V0IGdsb2JhbCBlbnNlbWJsZSBsaW1pdHMgY29uZmlndXJhdGlvblxuICogVmFsdWVzIGFyZSB2YWxpZGF0ZWQgYWdhaW5zdCBoYXJkIGxpbWl0c1xuICpcbiAqIEBwYXJhbSBjb25maWcgLSBDb25maWd1cmF0aW9uIG9iamVjdCB3aXRoIGRlc2lyZWQgbGltaXRzXG4gKiBAZXhhbXBsZVxuICogc2V0R2xvYmFsRW5zZW1ibGVMaW1pdHMoe1xuICogICBtYXhFbGVtZW50czogMTAwLFxuICogICBtYXhOZXN0aW5nRGVwdGg6IDMsXG4gKiAgIG1heEFjdGl2YXRpb25UaW1lOiA2MDAwMFxuICogfSk7XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRHbG9iYWxFbnNlbWJsZUxpbWl0cyhjb25maWc6IEVuc2VtYmxlTGltaXRzQ29uZmlnKTogdm9pZCB7XG4gIGNvbnN0IHByZXZpb3VzQ29uZmlnID0geyAuLi5nbG9iYWxDb25maWcgfTtcbiAgY29uc3QgcHJldmlvdXNLZXlzID0gT2JqZWN0LmtleXMocHJldmlvdXNDb25maWcpO1xuICBnbG9iYWxDb25maWcgPSB7IC4uLmNvbmZpZyB9O1xuICBjb25zdCBuZXdLZXlzID0gT2JqZWN0LmtleXMoY29uZmlnKTtcblxuICAvLyBEZXRlcm1pbmUgd2hhdCBjaGFuZ2VkIGZvciB0aGUgYXVkaXQgdHJhaWxcbiAgY29uc3QgYWRkZWRLZXlzID0gbmV3S2V5cy5maWx0ZXIoayA9PiAhcHJldmlvdXNLZXlzLmluY2x1ZGVzKGspKTtcbiAgY29uc3QgcmVtb3ZlZEtleXMgPSBwcmV2aW91c0tleXMuZmlsdGVyKGsgPT4gIW5ld0tleXMuaW5jbHVkZXMoaykpO1xuICBjb25zdCBtb2RpZmllZEtleXMgPSBuZXdLZXlzLmZpbHRlcihrID0+XG4gICAgcHJldmlvdXNLZXlzLmluY2x1ZGVzKGspICYmXG4gICAgcHJldmlvdXNDb25maWdbayBhcyBrZXlvZiBFbnNlbWJsZUxpbWl0c0NvbmZpZ10gIT09IGNvbmZpZ1trIGFzIGtleW9mIEVuc2VtYmxlTGltaXRzQ29uZmlnXVxuICApO1xuXG4gIGNvbnN0IHRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgY29uc3Qgc3VtbWFyeSA9IGAke2FkZGVkS2V5cy5sZW5ndGh9IGFkZGVkLCAke3JlbW92ZWRLZXlzLmxlbmd0aH0gcmVtb3ZlZCwgJHttb2RpZmllZEtleXMubGVuZ3RofSBtb2RpZmllZGA7XG5cbiAgLy8gSW5mbyBsZXZlbDogY29uY2lzZSBzdW1tYXJ5IGZvciBub3JtYWwgb3BlcmF0aW9uXG4gIGxvZ2dlci5pbmZvKCdHbG9iYWwgZW5zZW1ibGUgbGltaXRzIGNvbmZpZ3VyYXRpb24gdXBkYXRlZCcsIHtcbiAgICB0aW1lc3RhbXAsXG4gICAgc3VtbWFyeSxcbiAgICBjb25maWd1cmVkS2V5czogbmV3S2V5c1xuICB9KTtcblxuICAvLyBEZWJ1ZyBsZXZlbDogY29tcGxldGUgYXVkaXQgdHJhaWwgZm9yIHRyb3VibGVzaG9vdGluZ1xuICBsb2dnZXIuZGVidWcoJ0dsb2JhbCBlbnNlbWJsZSBsaW1pdHMgY29uZmlndXJhdGlvbiBhdWRpdCB0cmFpbCcsIHtcbiAgICB0aW1lc3RhbXAsXG4gICAgcHJldmlvdXNDb25maWc6IHByZXZpb3VzS2V5cy5sZW5ndGggPiAwID8gcHJldmlvdXNDb25maWcgOiAnKG5vIHByZXZpb3VzIGNvbmZpZ3VyYXRpb24pJyxcbiAgICBuZXdDb25maWc6IGNvbmZpZyxcbiAgICBjaGFuZ2VzOiB7XG4gICAgICBhZGRlZDogYWRkZWRLZXlzLmxlbmd0aCA+IDAgPyBhZGRlZEtleXMgOiB1bmRlZmluZWQsXG4gICAgICByZW1vdmVkOiByZW1vdmVkS2V5cy5sZW5ndGggPiAwID8gcmVtb3ZlZEtleXMgOiB1bmRlZmluZWQsXG4gICAgICBtb2RpZmllZDogbW9kaWZpZWRLZXlzLmxlbmd0aCA+IDAgPyBtb2RpZmllZEtleXMubWFwKGsgPT4gKHtcbiAgICAgICAga2V5OiBrLFxuICAgICAgICBmcm9tOiBwcmV2aW91c0NvbmZpZ1trIGFzIGtleW9mIEVuc2VtYmxlTGltaXRzQ29uZmlnXSxcbiAgICAgICAgdG86IGNvbmZpZ1trIGFzIGtleW9mIEVuc2VtYmxlTGltaXRzQ29uZmlnXVxuICAgICAgfSkpIDogdW5kZWZpbmVkXG4gICAgfSxcbiAgICBzdW1tYXJ5LFxuICAgIGltcGFjdDogJ05ldyBsaW1pdHMgYXBwbHkgdG8gZW5zZW1ibGVzIGNyZWF0ZWQgb3IgYWN0aXZhdGVkIGFmdGVyIHRoaXMgY2hhbmdlLiBFeGlzdGluZyBjYWNoZWQgbGltaXRzIGFyZSBub3QgYWZmZWN0ZWQgdW50aWwgaW52YWxpZGF0ZUxpbWl0c0NhY2hlKCkgaXMgY2FsbGVkLidcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IGN1cnJlbnQgZ2xvYmFsIGVuc2VtYmxlIGxpbWl0cyBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBDb3B5IG9mIGN1cnJlbnQgZ2xvYmFsIGNvbmZpZ1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0R2xvYmFsRW5zZW1ibGVMaW1pdHMoKTogUmVhZG9ubHk8RW5zZW1ibGVMaW1pdHNDb25maWc+IHtcbiAgcmV0dXJuIHsgLi4uZ2xvYmFsQ29uZmlnIH07XG59XG5cbi8qKlxuICogUmVzZXQgZ2xvYmFsIGVuc2VtYmxlIGxpbWl0cyB0byBkZWZhdWx0cyAoY2xlYXJzIGFsbCBvdmVycmlkZXMpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldEdsb2JhbEVuc2VtYmxlTGltaXRzKCk6IHZvaWQge1xuICBjb25zdCBwcmV2aW91c0NvbmZpZyA9IHsgLi4uZ2xvYmFsQ29uZmlnIH07XG4gIGNvbnN0IGhhZFByZXZpb3VzQ29uZmlnID0gT2JqZWN0LmtleXMocHJldmlvdXNDb25maWcpLmxlbmd0aCA+IDA7XG4gIGdsb2JhbENvbmZpZyA9IHt9O1xuXG4gIGNvbnN0IHRpbWVzdGFtcCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgY29uc3QgY2xlYXJlZEtleXMgPSBoYWRQcmV2aW91c0NvbmZpZyA/IE9iamVjdC5rZXlzKHByZXZpb3VzQ29uZmlnKSA6IFtdO1xuXG4gIC8vIEluZm8gbGV2ZWw6IGNvbmNpc2Ugc3VtbWFyeSBmb3Igbm9ybWFsIG9wZXJhdGlvblxuICBsb2dnZXIuaW5mbygnR2xvYmFsIGVuc2VtYmxlIGxpbWl0cyBjb25maWd1cmF0aW9uIHJlc2V0IHRvIGRlZmF1bHRzJywge1xuICAgIHRpbWVzdGFtcCxcbiAgICBjbGVhcmVkQ291bnQ6IGNsZWFyZWRLZXlzLmxlbmd0aFxuICB9KTtcblxuICAvLyBEZWJ1ZyBsZXZlbDogY29tcGxldGUgYXVkaXQgdHJhaWwgZm9yIHRyb3VibGVzaG9vdGluZ1xuICBpZiAoaGFkUHJldmlvdXNDb25maWcpIHtcbiAgICBsb2dnZXIuZGVidWcoJ0dsb2JhbCBlbnNlbWJsZSBsaW1pdHMgcmVzZXQgYXVkaXQgdHJhaWwnLCB7XG4gICAgICB0aW1lc3RhbXAsXG4gICAgICBwcmV2aW91c0NvbmZpZyxcbiAgICAgIGNsZWFyZWRLZXlzLFxuICAgICAgbmV3Q29uZmlnOiAnKHVzaW5nIGRlZmF1bHRzIC0gZW52aXJvbm1lbnQgdmFyaWFibGVzIGFuZCBwZXItZW5zZW1ibGUgb3ZlcnJpZGVzIHN0aWxsIGFwcGx5KScsXG4gICAgICBpbXBhY3Q6ICdFbnNlbWJsZXMgd2lsbCBub3cgdXNlIGVudmlyb25tZW50IHZhcmlhYmxlcyBvciBidWlsdC1pbiBkZWZhdWx0cy4gRXhpc3RpbmcgY2FjaGVkIGxpbWl0cyBhcmUgbm90IGFmZmVjdGVkIHVudGlsIGludmFsaWRhdGVMaW1pdHNDYWNoZSgpIGlzIGNhbGxlZC4nXG4gICAgfSk7XG4gIH1cbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT0gRUZGRUNUSVZFIExJTUlUUyBDQUxDVUxBVElPTiA9PT09PT09PT09PT09PT09PT09PVxuLyoqXG4gKiBSZXNvbHZlZCBlbnNlbWJsZSBsaW1pdHMgc3RydWN0dXJlXG4gKiBVc2VzIG51bWJlciB0eXBlIChub3QgbGl0ZXJhbCB0eXBlcykgc2luY2UgdmFsdWVzIGFyZSBjb21wdXRlZCBhdCBydW50aW1lXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRFbnNlbWJsZUxpbWl0cyB7XG4gIHJlYWRvbmx5IE1BWF9FTEVNRU5UUzogbnVtYmVyO1xuICByZWFkb25seSBNQVhfTkVTVElOR19ERVBUSDogbnVtYmVyO1xuICByZWFkb25seSBNQVhfQUNUSVZBVElPTl9USU1FOiBudW1iZXI7XG4gIHJlYWRvbmx5IE1BWF9DT05URVhUX1NJWkU6IG51bWJlcjtcbiAgcmVhZG9ubHkgTUFYX0NPTlRFWFRfVkFMVUVfU0laRTogbnVtYmVyO1xuICByZWFkb25seSBNQVhfREVQRU5ERU5DSUVTOiBudW1iZXI7XG4gIHJlYWRvbmx5IE1BWF9DT05ESVRJT05fTEVOR1RIOiBudW1iZXI7XG59XG5cbi8qKlxuICogR2V0IGVmZmVjdGl2ZSBsaW1pdHMgd2l0aCBwcm9wZXIgcHJpb3JpdHk6XG4gKiBQZXItZW5zZW1ibGUgb3ZlcnJpZGUgPiBHbG9iYWwgY29uZmlnID4gRW52aXJvbm1lbnQgdmFyaWFibGUgPiBEZWZhdWx0XG4gKlxuICogQHBhcmFtIHBlckVuc2VtYmxlT3ZlcnJpZGVzIC0gT3B0aW9uYWwgcGVyLWVuc2VtYmxlIGxpbWl0IG92ZXJyaWRlc1xuICogQHJldHVybnMgUmVzb2x2ZWQgbGltaXRzIG9iamVjdFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RWZmZWN0aXZlTGltaXRzKHBlckVuc2VtYmxlT3ZlcnJpZGVzPzogUGFydGlhbDxFbnNlbWJsZUxpbWl0c0NvbmZpZz4pOiBSZXNvbHZlZEVuc2VtYmxlTGltaXRzIHtcbiAgLy8gSGVscGVyIHRvIHJlc29sdmUgYSBzaW5nbGUgbGltaXQgdmFsdWVcbiAgY29uc3QgcmVzb2x2ZUxpbWl0ID0gKFxuICAgIGtleToga2V5b2YgRW5zZW1ibGVMaW1pdHNDb25maWcsXG4gICAgZW52VmFyOiBzdHJpbmcsXG4gICAgZGVmYXVsdFZhbDogbnVtYmVyLFxuICAgIG1pblZhbDogbnVtYmVyLFxuICAgIG1heFZhbDogbnVtYmVyXG4gICk6IG51bWJlciA9PiB7XG4gICAgLy8gUHJpb3JpdHk6IHBlci1lbnNlbWJsZSA+IGdsb2JhbCA+IGVudiA+IGRlZmF1bHRcbiAgICBsZXQgdmFsdWUgPSBkZWZhdWx0VmFsO1xuXG4gICAgLy8gQ2hlY2sgZW52aXJvbm1lbnQgdmFyaWFibGVcbiAgICBjb25zdCBlbnZWYWx1ZSA9IHBhcnNlRW52SW50KGVudlZhciwgZGVmYXVsdFZhbCwgbWluVmFsLCBtYXhWYWwsICdFbnNlbWJsZSBsaW1pdCcpO1xuICAgIGlmIChwcm9jZXNzLmVudltlbnZWYXJdICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlID0gZW52VmFsdWU7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZ2xvYmFsIGNvbmZpZ1xuICAgIGlmIChnbG9iYWxDb25maWdba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB2YWx1ZSA9IE1hdGgubWF4KG1pblZhbCwgTWF0aC5taW4obWF4VmFsLCBnbG9iYWxDb25maWdba2V5XSEpKTtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBwZXItZW5zZW1ibGUgb3ZlcnJpZGVcbiAgICBpZiAocGVyRW5zZW1ibGVPdmVycmlkZXM/LltrZXldICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHZhbHVlID0gTWF0aC5tYXgobWluVmFsLCBNYXRoLm1pbihtYXhWYWwsIHBlckVuc2VtYmxlT3ZlcnJpZGVzW2tleV0hKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIHJldHVybiB7XG4gICAgTUFYX0VMRU1FTlRTOiByZXNvbHZlTGltaXQoJ21heEVsZW1lbnRzJywgJ0VOU0VNQkxFX01BWF9FTEVNRU5UUycsIDUwLFxuICAgICAgRU5TRU1CTEVfTUlOX0xJTUlUUy5NQVhfRUxFTUVOVFMsIEVOU0VNQkxFX0hBUkRfTElNSVRTLk1BWF9FTEVNRU5UUyksXG4gICAgTUFYX05FU1RJTkdfREVQVEg6IHJlc29sdmVMaW1pdCgnbWF4TmVzdGluZ0RlcHRoJywgJ0VOU0VNQkxFX01BWF9ORVNUSU5HX0RFUFRIJywgNSxcbiAgICAgIEVOU0VNQkxFX01JTl9MSU1JVFMuTUFYX05FU1RJTkdfREVQVEgsIEVOU0VNQkxFX0hBUkRfTElNSVRTLk1BWF9ORVNUSU5HX0RFUFRIKSxcbiAgICBNQVhfQUNUSVZBVElPTl9USU1FOiByZXNvbHZlTGltaXQoJ21heEFjdGl2YXRpb25UaW1lJywgJ0VOU0VNQkxFX01BWF9BQ1RJVkFUSU9OX1RJTUUnLCAzMDAwMCxcbiAgICAgIEVOU0VNQkxFX01JTl9MSU1JVFMuTUFYX0FDVElWQVRJT05fVElNRSwgRU5TRU1CTEVfSEFSRF9MSU1JVFMuTUFYX0FDVElWQVRJT05fVElNRSksXG4gICAgTUFYX0NPTlRFWFRfU0laRTogcmVzb2x2ZUxpbWl0KCdtYXhDb250ZXh0U2l6ZScsICdFTlNFTUJMRV9NQVhfQ09OVEVYVF9TSVpFJywgMTAwMCxcbiAgICAgIEVOU0VNQkxFX01JTl9MSU1JVFMuTUFYX0NPTlRFWFRfU0laRSwgRU5TRU1CTEVfSEFSRF9MSU1JVFMuTUFYX0NPTlRFWFRfU0laRSksXG4gICAgTUFYX0NPTlRFWFRfVkFMVUVfU0laRTogcmVzb2x2ZUxpbWl0KCdtYXhDb250ZXh0VmFsdWVTaXplJywgJ0VOU0VNQkxFX01BWF9DT05URVhUX1ZBTFVFX1NJWkUnLCAxMDAwMCxcbiAgICAgIEVOU0VNQkxFX01JTl9MSU1JVFMuTUFYX0NPTlRFWFRfVkFMVUVfU0laRSwgRU5TRU1CTEVfSEFSRF9MSU1JVFMuTUFYX0NPTlRFWFRfVkFMVUVfU0laRSksXG4gICAgTUFYX0RFUEVOREVOQ0lFUzogcmVzb2x2ZUxpbWl0KCdtYXhEZXBlbmRlbmNpZXMnLCAnRU5TRU1CTEVfTUFYX0RFUEVOREVOQ0lFUycsIDEwLFxuICAgICAgRU5TRU1CTEVfTUlOX0xJTUlUUy5NQVhfREVQRU5ERU5DSUVTLCBFTlNFTUJMRV9IQVJEX0xJTUlUUy5NQVhfREVQRU5ERU5DSUVTKSxcbiAgICBNQVhfQ09ORElUSU9OX0xFTkdUSDogcmVzb2x2ZUxpbWl0KCdtYXhDb25kaXRpb25MZW5ndGgnLCAnRU5TRU1CTEVfTUFYX0NPTkRJVElPTl9MRU5HVEgnLCAyMDAsXG4gICAgICBFTlNFTUJMRV9NSU5fTElNSVRTLk1BWF9DT05ESVRJT05fTEVOR1RILCBFTlNFTUJMRV9IQVJEX0xJTUlUUy5NQVhfQ09ORElUSU9OX0xFTkdUSClcbiAgfTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT0gREVGQVVMVCBMSU1JVFMgKEJhY2t3YXJkcyBDb21wYXRpYmxlKSA9PT09PT09PT09PT09PT09PT09PVxuLyoqXG4gKiBSZXNvdXJjZSBsaW1pdHMgdG8gcHJldmVudCBEb1MgYXR0YWNrcyBhbmQgZW5zdXJlIHN5c3RlbSBzdGFiaWxpdHlcbiAqXG4gKiBOb3RlOiBSYXRlIGxpbWl0aW5nIGlzIG5vdCBpbXBsZW1lbnRlZCBhdCB0aGUgRW5zZW1ibGUgbGV2ZWwgYmVjYXVzZTpcbiAqIDEuIFRoZSBhY3RpdmF0aW9uSW5Qcm9ncmVzcyBmbGFnIGFscmVhZHkgcHJldmVudHMgY29uY3VycmVudCBhY3RpdmF0aW9uc1xuICogMi4gUmF0ZSBsaW1pdGluZyBzaG91bGQgYmUgaGFuZGxlZCBhdCB0aGUgaGFuZGxlci9BUEkgbGV2ZWwsIG5vdCBpbiB0aGUgZG9tYWluIG1vZGVsXG4gKiAzLiBEaWZmZXJlbnQgZGVwbG95bWVudCBzY2VuYXJpb3MgbWF5IGhhdmUgZGlmZmVyZW50IHJhdGUgbGltaXRpbmcgcmVxdWlyZW1lbnRzXG4gKlxuICogQ09ORklHVVJBQklMSVRZOiBVc2UgZ2V0RWZmZWN0aXZlTGltaXRzKCkgdG8gZ2V0IGxpbWl0cyB0aGF0IHJlc3BlY3RcbiAqIGVudmlyb25tZW50IHZhcmlhYmxlcywgZ2xvYmFsIGNvbmZpZywgYW5kIHBlci1lbnNlbWJsZSBvdmVycmlkZXMuXG4gKiBUaGlzIGNvbnN0YW50IHByb3ZpZGVzIHRoZSBiYXNlIGRlZmF1bHRzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAqL1xuZXhwb3J0IGNvbnN0IEVOU0VNQkxFX0xJTUlUUyA9IHtcbiAgTUFYX0VMRU1FTlRTOiA1MCwgICAgICAgICAgICAgICAgICAgIC8vIE1heGltdW0gZWxlbWVudHMgaW4gYW4gZW5zZW1ibGVcbiAgTUFYX05FU1RJTkdfREVQVEg6IDUsICAgICAgICAgICAgICAgIC8vIE1heGltdW0gZGVwdGggb2YgbmVzdGVkIGVuc2VtYmxlc1xuICBNQVhfQUNUSVZBVElPTl9USU1FOiAzMDAwMCwgICAgICAgICAgLy8gMzAgc2Vjb25kcyBtYXggYWN0aXZhdGlvbiB0aW1lXG4gIE1BWF9DT05URVhUX1NJWkU6IDEwMDAsICAgICAgICAgICAgICAvLyBNYXhpbXVtIGtleXMgaW4gc2hhcmVkIGNvbnRleHRcbiAgTUFYX0NPTlRFWFRfVkFMVUVfU0laRTogMTAwMDAsICAgICAgIC8vIE1heGltdW0gc2l6ZSBvZiBhIGNvbnRleHQgdmFsdWUgKGJ5dGVzKVxuICBNQVhfREVQRU5ERU5DSUVTOiAxMCwgICAgICAgICAgICAgICAgLy8gTWF4aW11bSBkZXBlbmRlbmNpZXMgcGVyIGVsZW1lbnRcbiAgTUFYX0NPTkRJVElPTl9MRU5HVEg6IDIwMCAgICAgICAgICAgIC8vIE1heGltdW0gbGVuZ3RoIG9mIGFjdGl2YXRpb24gY29uZGl0aW9uXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIERlZmF1bHQgdmFsdWVzIGZvciBlbnNlbWJsZSBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBjb25zdCBFTlNFTUJMRV9ERUZBVUxUUyA9IHtcbiAgQUNUSVZBVElPTl9TVFJBVEVHWTogJ3NlcXVlbnRpYWwnIGFzIGNvbnN0LFxuICBDT05GTElDVF9SRVNPTFVUSU9OOiAnbGFzdC13cml0ZScgYXMgY29uc3QsXG4gIEVMRU1FTlRfUk9MRTogJ3N1cHBvcnQnIGFzIGNvbnN0LFxuICBQUklPUklUWTogNTAsICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWlkLXJhbmdlIHByaW9yaXR5ICgwLTEwMClcbiAgQUxMT1dfTkVTVEVEOiB0cnVlLFxuICBBQ1RJVkFUSU9OX1RJTUVPVVQ6IDUwMDAsICAgICAgICAgICAgLy8gNSBzZWNvbmRzIHBlciBlbGVtZW50XG4gIE1BWF9ORVNUSU5HX0RFUFRIOiA1LFxuICBDT05URVhUX1NIQVJJTkc6ICdzZWxlY3RpdmUnIGFzIGNvbnN0XG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIFN1cHBvcnRlZCBhY3RpdmF0aW9uIHN0cmF0ZWdpZXNcbiAqIE11c3QgbWF0Y2ggQWN0aXZhdGlvblN0cmF0ZWd5IHR5cGUgaW4gdHlwZXMudHNcbiAqL1xuZXhwb3J0IGNvbnN0IEFDVElWQVRJT05fU1RSQVRFR0lFUyA9IFtcbiAgJ2FsbCcsXG4gICdzZXF1ZW50aWFsJyxcbiAgJ2xhenknLFxuICAnY29uZGl0aW9uYWwnLFxuICAncHJpb3JpdHknXG5dIGFzIGNvbnN0O1xuXG4vKipcbiAqIFN1cHBvcnRlZCBjb25mbGljdCByZXNvbHV0aW9uIHN0cmF0ZWdpZXNcbiAqL1xuZXhwb3J0IGNvbnN0IENPTkZMSUNUX1NUUkFURUdJRVMgPSBbXG4gICdsYXN0LXdyaXRlJyxcbiAgJ2ZpcnN0LXdyaXRlJyxcbiAgJ3ByaW9yaXR5JyxcbiAgJ21lcmdlJyxcbiAgJ2Vycm9yJ1xuXSBhcyBjb25zdDtcblxuLyoqXG4gKiBFbGVtZW50IHJvbGVzIHdpdGhpbiBhbiBlbnNlbWJsZVxuICovXG5leHBvcnQgY29uc3QgRUxFTUVOVF9ST0xFUyA9IFtcbiAgJ3ByaW1hcnknLFxuICAnc3VwcG9ydCcsXG4gICdvdmVycmlkZScsXG4gICdtb25pdG9yJyxcbiAgJ2NvcmUnICAgLy8gTGVnYWN5IGFsaWFzIGZvciAncHJpbWFyeScg4oCUIGFjY2VwdGVkIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuXSBhcyBjb25zdDtcblxuLyoqXG4gKiBBY3RpdmF0aW9uIG1vZGVzIGZvciBlbGVtZW50c1xuICovXG5leHBvcnQgY29uc3QgQUNUSVZBVElPTl9NT0RFUyA9IFtcbiAgJ2Fsd2F5cycsXG4gICdvbi1kZW1hbmQnLFxuICAnY29uZGl0aW9uYWwnXG5dIGFzIGNvbnN0O1xuXG4vKipcbiAqIFNlY3VyaXR5IGV2ZW50IHR5cGVzIGZvciBlbnNlbWJsZSBvcGVyYXRpb25zXG4gKiBUaGVzZSBhcmUgbG9nZ2VkIHZpYSBTZWN1cml0eU1vbml0b3IgZm9yIGF1ZGl0IHRyYWlsc1xuICovXG5leHBvcnQgY29uc3QgRU5TRU1CTEVfU0VDVVJJVFlfRVZFTlRTID0ge1xuICBDSVJDVUxBUl9ERVBFTkRFTkNZOiAnRU5TRU1CTEVfQ0lSQ1VMQVJfREVQRU5ERU5DWScsXG4gIFJFU09VUkNFX0xJTUlUX0VYQ0VFREVEOiAnRU5TRU1CTEVfUkVTT1VSQ0VfTElNSVRfRVhDRUVERUQnLFxuICBBQ1RJVkFUSU9OX1RJTUVPVVQ6ICdFTlNFTUJMRV9BQ1RJVkFUSU9OX1RJTUVPVVQnLFxuICBBQ1RJVkFUSU9OX0ZBSUxFRDogJ0VOU0VNQkxFX0FDVElWQVRJT05fRkFJTEVEJyxcbiAgU1VTUElDSU9VU19DT05ESVRJT046ICdFTlNFTUJMRV9TVVNQSUNJT1VTX0NPTkRJVElPTicsXG4gIENPTkRJVElPTl9FVkFMVUFUSU9OX0ZBSUxFRDogJ0VOU0VNQkxFX0NPTkRJVElPTl9FVkFMVUFUSU9OX0ZBSUxFRCcsXG4gIE5FU1RFRF9ERVBUSF9FWENFRURFRDogJ0VOU0VNQkxFX05FU1RFRF9ERVBUSF9FWENFRURFRCcsXG4gIENPTlRFWFRfU0laRV9FWENFRURFRDogJ0VOU0VNQkxFX0NPTlRFWFRfU0laRV9FWENFRURFRCcsXG4gIENPTlRFWFRfVkFMVUVfVE9PX0xBUkdFOiAnRU5TRU1CTEVfQ09OVEVYVF9WQUxVRV9UT09fTEFSR0UnLFxuICBTQVZFRDogJ0VOU0VNQkxFX1NBVkVEJyxcbiAgSU1QT1JURUQ6ICdFTlNFTUJMRV9JTVBPUlRFRCcsXG4gIERFTEVURUQ6ICdFTlNFTUJMRV9ERUxFVEVEJyxcbiAgQUNUSVZBVEVEOiAnRU5TRU1CTEVfQUNUSVZBVEVEJyxcbiAgREVBQ1RJVkFURUQ6ICdFTlNFTUJMRV9ERUFDVElWQVRFRCdcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogRXJyb3IgbWVzc2FnZXMgZm9yIHZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IEVOU0VNQkxFX0VSUk9SUyA9IHtcbiAgVE9PX01BTllfRUxFTUVOVFM6IGBFbnNlbWJsZSBjYW5ub3QgY29udGFpbiBtb3JlIHRoYW4gJHtFTlNFTUJMRV9MSU1JVFMuTUFYX0VMRU1FTlRTfSBlbGVtZW50c2AsXG4gIE5FU1RJTkdfVE9PX0RFRVA6IGBFbnNlbWJsZSBuZXN0aW5nIGRlcHRoIGNhbm5vdCBleGNlZWQgJHtFTlNFTUJMRV9MSU1JVFMuTUFYX05FU1RJTkdfREVQVEh9YCxcbiAgQ0lSQ1VMQVJfREVQRU5ERU5DWTogJ0NpcmN1bGFyIGRlcGVuZGVuY3kgZGV0ZWN0ZWQgaW4gZW5zZW1ibGUnLFxuICBJTlZBTElEX1NUUkFURUdZOiAnSW52YWxpZCBhY3RpdmF0aW9uIHN0cmF0ZWd5JyxcbiAgSU5WQUxJRF9DT05GTElDVF9SRVNPTFVUSU9OOiAnSW52YWxpZCBjb25mbGljdCByZXNvbHV0aW9uIHN0cmF0ZWd5JyxcbiAgSU5WQUxJRF9FTEVNRU5UX1JPTEU6ICdJbnZhbGlkIGVsZW1lbnQgcm9sZScsXG4gIElOVkFMSURfQUNUSVZBVElPTl9NT0RFOiAnSW52YWxpZCBhY3RpdmF0aW9uIG1vZGUnLFxuICBFTEVNRU5UX05PVF9GT1VORDogJ0VsZW1lbnQgbm90IGZvdW5kIGluIGVuc2VtYmxlJyxcbiAgQUNUSVZBVElPTl9USU1FT1VUOiAnRW5zZW1ibGUgYWN0aXZhdGlvbiB0aW1lZCBvdXQnLFxuICBDT05URVhUX09WRVJGTE9XOiAnU2hhcmVkIGNvbnRleHQgc2l6ZSBleGNlZWRlZCBsaW1pdHMnLFxuICBFTEVNRU5UX0xPQURfRkFJTEVEOiAnRmFpbGVkIHRvIGxvYWQgZWxlbWVudCcsXG4gIENPTkRJVElPTl9FVkFMVUFUSU9OX0ZBSUxFRDogJ0ZhaWxlZCB0byBldmFsdWF0ZSBhY3RpdmF0aW9uIGNvbmRpdGlvbidcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogUmVnZXggcGF0dGVybnMgZm9yIHZhbGlkYXRpb25cbiAqL1xuZXhwb3J0IGNvbnN0IEVOU0VNQkxFX1BBVFRFUk5TID0ge1xuICAvLyBDb25kaXRpb24gcGF0dGVybiAtIGFsbG93cyBzYWZlIGNvbXBhcmlzb24gZXhwcmVzc2lvbnNcbiAgLy8gQWxsb3dzIGFsbW9zdCBhbnkgY2hhcmFjdGVyIEVYQ0VQVCBvYnZpb3VzbHkgZGFuZ2Vyb3VzIG9uZXMgKGJhY2t0aWNrcywgJCwgYnJhY2VzKVxuICAvLyBUaGUgcmVhbCBzZWN1cml0eSBlbmZvcmNlbWVudCBoYXBwZW5zIGluOlxuICAvLyAxLiBEQU5HRVJPVVNfQ09ORElUSU9OX1BBVFRFUk5TIGNoZWNrIChibG9ja3MgZXZhbCwgcmVxdWlyZSwgZXRjLilcbiAgLy8gMi4gVk0gc2FuZGJveCBleGVjdXRpb24gKHByZXZlbnRzIGNvZGUgaW5qZWN0aW9uKVxuICAvL1xuICAvLyBUaGlzIHBhdHRlcm4ganVzdCBwcmV2ZW50cyB0ZW1wbGF0ZSBsaXRlcmFscyAoYCksIHZhcmlhYmxlIGludGVycG9sYXRpb24gKCR7fSksXG4gIC8vIGFuZCBjb2RlIGJsb2NrcyAoe30pLiBFdmVyeXRoaW5nIGVsc2UgaXMgYWxsb3dlZCBhbmQgd2lsbCBiZSBzYWZlbHkgZXZhbHVhdGVkIGluIHRoZSBWTS5cbiAgQ09ORElUSU9OX1BBVFRFUk46IC9eW15gJHt9XSskLyxcblxuICAvLyBFbGVtZW50IG5hbWUgcGF0dGVybiAoYWxwaGFudW1lcmljLCBoeXBoZW5zLCB1bmRlcnNjb3JlcylcbiAgRUxFTUVOVF9OQU1FX1BBVFRFUk46IC9eW2EtekEtWjAtOV8tXSskL1xufSBhcyBjb25zdDtcblxuLyoqXG4gKiBEYW5nZXJvdXMga2V5d29yZHMgdGhhdCBzaG91bGQgYmUgcmVqZWN0ZWQgaW4gY29uZGl0aW9uc1xuICpcbiAqIFRoZXNlIHBhdHRlcm5zIGFyZSBjaGVja2VkIHNlcGFyYXRlbHkgZnJvbSBDT05ESVRJT05fUEFUVEVSTiBmb3Igc2VjdXJpdHkuXG4gKiBOb3RlOiBXZSBmb2N1cyBvbiBkYW5nZXJvdXMgY29kZSBleGVjdXRpb24gcGF0dGVybnMgcmF0aGVyIHRoYW4gdW5zdXBwb3J0ZWRcbiAqIG9wZXJhdG9ycywgc2luY2UgY29uZGl0aW9uIGV2YWx1YXRpb24gaXNuJ3QgaW1wbGVtZW50ZWQgeWV0LiBXaGVuIGl0IGlzXG4gKiBpbXBsZW1lbnRlZCwgdGhlIGV2YWx1YXRvciB3aWxsIGhhbmRsZSBvcGVyYXRvciBzdXBwb3J0IHByb3Blcmx5LlxuICovXG5leHBvcnQgY29uc3QgREFOR0VST1VTX0NPTkRJVElPTl9QQVRURVJOUyA9IFtcbiAgLy8gRnVuY3Rpb24gY2FsbHMgYW5kIGNvZGUgZXhlY3V0aW9uXG4gIC9cXGJldmFsXFxiL2ksXG4gIC9cXGJGdW5jdGlvblxcYi9pLFxuICAvXFxicmVxdWlyZVxcYi9pLFxuICAvXFxiaW1wb3J0XFxiL2ksXG4gIC9cXGJleHBvcnRcXGIvaSxcblxuICAvLyBQcm9jZXNzIGFuZCBnbG9iYWwgYWNjZXNzXG4gIC9cXGJwcm9jZXNzXFxiL2ksXG4gIC9cXGJnbG9iYWxcXGIvaSxcbiAgL1xcYndpbmRvd1xcYi9pLFxuICAvXFxiZG9jdW1lbnRcXGIvaSxcblxuICAvLyBQcm90b3R5cGUgcG9sbHV0aW9uXG4gIC9fX3Byb3RvX18vaSxcbiAgL1xcYmNvbnN0cnVjdG9yXFxiL2ksXG4gIC9cXC5wcm90b3R5cGVcXGIvaSxcblxuICAvLyBEYW5nZXJvdXMgb3BlcmF0b3JzXG4gIC9bOyw/Ol0vLCAgICAgICAgICAgICAgICAgICAgLy8gU2VtaWNvbG9uLCBjb21tYSwgdGVybmFyeVxuICAvKD88IVs9ITw+XSk9KD8hWz1dKS8sICAgICAgIC8vIEFzc2lnbm1lbnQgKGJ1dCBhbGxvdyA9PSwgIT0sID09PSwgIT09LCA8PSwgPj0pXG4gIC9cXCs9fC09fFxcKj18XFwvPXwlPS8sICAgICAgICAgLy8gQ29tcG91bmQgYXNzaWdubWVudFxuXG4gIC8vIEVtcHR5IG9yIHdoaXRlc3BhY2Ugb25seVxuICAvXlxccyokL1xuXSBhcyBjb25zdDtcbiJdfQ==