UNPKG

@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.

121 lines 18.8 kB
/** * Security-related constants and limits */ // Security and performance limits export const SECURITY_LIMITS = { MAX_PERSONA_SIZE_BYTES: 1024 * 1024 * 2, // 2MB max persona file size MAX_FILENAME_LENGTH: 255, // Max filename length MAX_PATH_DEPTH: 10, // Max directory depth for paths MAX_CONTENT_LENGTH: 500000, // Max element content length (500KB, ~1-5ms regex scan) MAX_YAML_LENGTH: 64 * 1024, // Max YAML frontmatter length (64KB) MAX_METADATA_FIELD_LENGTH: 1024, // Max individual metadata field length (1KB) MAX_FILE_SIZE: 1024 * 1024 * 2, // Max file size (2MB) RATE_LIMIT_REQUESTS: 100, // Max requests per window RATE_LIMIT_WINDOW_MS: 60 * 1000, // 1 minute window CACHE_TTL_MS: 5 * 60 * 1000, // 5 minute cache TTL MAX_SEARCH_RESULTS: 50, // Max search results to return MAX_BATCH_OPERATIONS: 50, // Max operations per batch request (Issue #221/#543) // Field-level validation limits — used across element managers and validators. // Centralized here so a single change applies everywhere and grep finds all usages. MAX_NAME_LENGTH: 100, // Element name field MAX_DESCRIPTION_LENGTH: 500, // Element description field MAX_DOCUMENTATION_FIELD_LENGTH: 64 * 1024, // Nested help/example docs in YAML/frontmatter MAX_ENUM_FIELD_LENGTH: 20, // Short enum-like fields (strategy, role, activation) MAX_TAG_LENGTH: 50, // Individual tag / category values MAX_COMMAND_ARG_LENGTH: 1000, // CLI command argument validation // Regex validation — content length caps per pattern complexity tier. // These are the defaults used by RegexValidator when no explicit maxLength is passed. // Low/medium are safe at MAX_CONTENT_LENGTH because they're O(n) linear time. // High-complexity patterns (nested quantifiers, ReDoS risk) are hard-capped at 1KB. MAX_REGEX_INPUT_LENGTH: 10000, // SafeRegex default for user-supplied patterns // YAML bomb detection threshold (SECURITY FIX #1298) // Maximum allowed alias-to-anchor amplification ratio // Set to 5:1 - balances security (early DoS detection) with usability (legitimate YAML patterns) // Rationale: Most legitimate YAML uses ≤3× amplification; 5× provides safety margin // while blocking exponential expansion attacks that typically start at 10×+ YAML_BOMB_AMPLIFICATION_THRESHOLD: 5 }; /** * Escalate severity level — higher severity takes precedence. * Extracted from UnicodeValidator and InputNormalizer to eliminate duplication (#1782-7). */ export function escalateSeverity(current, newSeverity) { const levels = { low: 1, medium: 2, high: 3, critical: 4 }; const currentLevel = current ? levels[current] : 0; return levels[newSeverity] > currentLevel ? newSeverity : (current || 'low'); } // Input validation patterns export const VALIDATION_PATTERNS = { SAFE_FILENAME: /^[a-zA-Z0-9][a-zA-Z0-9\-_.]{0,250}[a-zA-Z0-9]$/, SAFE_PATH: /^[a-zA-Z0-9:/\-_.~]{1,500}$/, SAFE_USERNAME: /^[a-zA-Z0-9][a-zA-Z0-9\-_.]{0,30}[a-zA-Z0-9]$/, SAFE_CATEGORY: /^[a-zA-Z][a-zA-Z0-9\-_]{0,20}$/, SAFE_EMAIL: /^[^\s@]{1,64}@[^\s@]{1,253}\.[^\s@]{1,63}$/, // RFC 5321 compliant limits // Field-appropriate patterns for sanitize-then-validate approach // These patterns validate AFTER sanitization, so they allow legitimate characters // For names: allow letters (including accented Latin), numbers, spaces, and basic punctuation // Uses Unicode property escapes for proper international support SAFE_NAME: /^[\p{L}\p{N}\s\-_.]+$/u, // For descriptions: allow broad punctuation for readability // Includes common symbols found in real-world portfolio descriptions: // #(C#/hashtags) +(C++) %(percentages) =(key=value) @(email/handles) // &(and) ~(approximate) *(emphasis) |(separators) {}(templates) // <>(angle brackets) $(currency) ^(caret) `(backtick) // →↔←↑↓(arrows) ✓✗(checkmarks) and other Unicode symbols SAFE_DESCRIPTION: /^[\p{L}\p{N}\p{P}\p{S}\s@#$%^&*+=~`|\\]+$/u, // For content: most permissive - ContentValidator handles security threats // This allows essentially anything since content validation is separate SAFE_CONTENT: /^[\s\S]*$/, // For filenames in create operations: strict ASCII only (different from SAFE_FILENAME which has length limits) SAFE_FILENAME_CREATE: /^[a-zA-Z0-9\-_.]+$/ }; /** * Human-readable descriptions for each validation pattern. * Used by ValidationService to produce actionable error messages. * * - `allowed`: short description of the character set * - `charTest`: single-character regex to identify which chars are invalid * - `structural` (optional): extra constraint not captured by charTest */ export const PATTERN_DESCRIPTIONS = { SAFE_NAME: { allowed: 'letters, numbers, spaces, hyphens, underscores, dots', charTest: /^[\p{L}\p{N}\s\-_.]$/u, }, SAFE_DESCRIPTION: { allowed: 'letters, numbers, symbols, spaces, and common punctuation', charTest: /^[\p{L}\p{N}\p{P}\p{S}\s@#$%^&*+=~`|\\]$/u, }, SAFE_CONTENT: { allowed: 'any characters', charTest: /^[\s\S]$/, }, SAFE_FILENAME_CREATE: { allowed: 'letters, numbers, hyphens, underscores, dots', charTest: /^[a-zA-Z0-9\-_.]$/, }, SAFE_FILENAME: { allowed: 'letters, numbers, hyphens, underscores, dots', charTest: /^[a-zA-Z0-9\-_.]$/, structural: 'must start and end with alphanumeric (max 252 chars)', }, SAFE_PATH: { allowed: 'letters, numbers, colons, slashes, hyphens, underscores, dots, tildes', charTest: /^[a-zA-Z0-9:/\-_.~]$/, }, SAFE_USERNAME: { allowed: 'letters, numbers, hyphens, underscores, dots', charTest: /^[a-zA-Z0-9\-_.]$/, structural: 'must start and end with alphanumeric (3-32 chars)', }, SAFE_CATEGORY: { allowed: 'letters, numbers, hyphens, underscores', charTest: /^[a-zA-Z0-9\-_]$/, structural: 'must start with a letter (max 21 chars)', }, SAFE_EMAIL: { allowed: 'letters, numbers, dots, hyphens, underscores, @', charTest: /^[^\s@]$/, }, }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlY3VyaXR5L2NvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGtDQUFrQztBQUNsQyxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUc7SUFDN0Isc0JBQXNCLEVBQUUsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUcsNEJBQTRCO0lBQ3RFLG1CQUFtQixFQUFFLEdBQUcsRUFBbUIsc0JBQXNCO0lBQ2pFLGNBQWMsRUFBRSxFQUFFLEVBQXdCLGdDQUFnQztJQUMxRSxrQkFBa0IsRUFBRSxNQUFNLEVBQWdCLHdEQUF3RDtJQUNsRyxlQUFlLEVBQUUsRUFBRSxHQUFHLElBQUksRUFBZ0IscUNBQXFDO0lBQy9FLHlCQUF5QixFQUFFLElBQUksRUFBVyw2Q0FBNkM7SUFDdkYsYUFBYSxFQUFFLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxFQUFXLHNCQUFzQjtJQUMvRCxtQkFBbUIsRUFBRSxHQUFHLEVBQWtCLDBCQUEwQjtJQUNwRSxvQkFBb0IsRUFBRSxFQUFFLEdBQUcsSUFBSSxFQUFVLGtCQUFrQjtJQUMzRCxZQUFZLEVBQUUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQWMscUJBQXFCO0lBQzlELGtCQUFrQixFQUFFLEVBQUUsRUFBb0IsK0JBQStCO0lBQ3pFLG9CQUFvQixFQUFFLEVBQUUsRUFBa0IscURBQXFEO0lBRS9GLCtFQUErRTtJQUMvRSxvRkFBb0Y7SUFDcEYsZUFBZSxFQUFFLEdBQUcsRUFBc0IscUJBQXFCO0lBQy9ELHNCQUFzQixFQUFFLEdBQUcsRUFBZSw0QkFBNEI7SUFDdEUsOEJBQThCLEVBQUUsRUFBRSxHQUFHLElBQUksRUFBRSwrQ0FBK0M7SUFDMUYscUJBQXFCLEVBQUUsRUFBRSxFQUFpQixzREFBc0Q7SUFDaEcsY0FBYyxFQUFFLEVBQUUsRUFBd0IsbUNBQW1DO0lBQzdFLHNCQUFzQixFQUFF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IGFuZCBsaW1pdHNcbiAqL1xuXG4vLyBTZWN1cml0eSBhbmQgcGVyZm9ybWFuY2UgbGltaXRzXG5leHBvcnQgY29uc3QgU0VDVVJJVFlfTElNSVRTID0ge1xuICBNQVhfUEVSU09OQV9TSVpFX0JZVEVTOiAxMDI0ICogMTAyNCAqIDIsICAvLyAyTUIgbWF4IHBlcnNvbmEgZmlsZSBzaXplXG4gIE1BWF9GSUxFTkFNRV9MRU5HVEg6IDI1NSwgICAgICAgICAgICAgICAgICAvLyBNYXggZmlsZW5hbWUgbGVuZ3RoXG4gIE1BWF9QQVRIX0RFUFRIOiAxMCwgICAgICAgICAgICAgICAgICAgICAgIC8vIE1heCBkaXJlY3RvcnkgZGVwdGggZm9yIHBhdGhzXG4gIE1BWF9DT05URU5UX0xFTkdUSDogNTAwMDAwLCAgICAgICAgICAgICAgIC8vIE1heCBlbGVtZW50IGNvbnRlbnQgbGVuZ3RoICg1MDBLQiwgfjEtNW1zIHJlZ2V4IHNjYW4pXG4gIE1BWF9ZQU1MX0xFTkdUSDogNjQgKiAxMDI0LCAgICAgICAgICAgICAgIC8vIE1heCBZQU1MIGZyb250bWF0dGVyIGxlbmd0aCAoNjRLQilcbiAgTUFYX01FVEFEQVRBX0ZJRUxEX0xFTkdUSDogMTAyNCwgICAgICAgICAgLy8gTWF4IGluZGl2aWR1YWwgbWV0YWRhdGEgZmllbGQgbGVuZ3RoICgxS0IpXG4gIE1BWF9GSUxFX1NJWkU6IDEwMjQgKiAxMDI0ICogMiwgICAgICAgICAgLy8gTWF4IGZpbGUgc2l6ZSAoMk1CKVxuICBSQVRFX0xJTUlUX1JFUVVFU1RTOiAxMDAsICAgICAgICAgICAgICAgICAvLyBNYXggcmVxdWVzdHMgcGVyIHdpbmRvd1xuICBSQVRFX0xJTUlUX1dJTkRPV19NUzogNjAgKiAxMDAwLCAgICAgICAgIC8vIDEgbWludXRlIHdpbmRvd1xuICBDQUNIRV9UVExfTVM6IDUgKiA2MCAqIDEwMDAsICAgICAgICAgICAgIC8vIDUgbWludXRlIGNhY2hlIFRUTFxuICBNQVhfU0VBUkNIX1JFU1VMVFM6IDUwLCAgICAgICAgICAgICAgICAgICAvLyBNYXggc2VhcmNoIHJlc3VsdHMgdG8gcmV0dXJuXG4gIE1BWF9CQVRDSF9PUEVSQVRJT05TOiA1MCwgICAgICAgICAgICAgICAgIC8vIE1heCBvcGVyYXRpb25zIHBlciBiYXRjaCByZXF1ZXN0IChJc3N1ZSAjMjIxLyM1NDMpXG5cbiAgLy8gRmllbGQtbGV2ZWwgdmFsaWRhdGlvbiBsaW1pdHMg4oCUIHVzZWQgYWNyb3NzIGVsZW1lbnQgbWFuYWdlcnMgYW5kIHZhbGlkYXRvcnMuXG4gIC8vIENlbnRyYWxpemVkIGhlcmUgc28gYSBzaW5nbGUgY2hhbmdlIGFwcGxpZXMgZXZlcnl3aGVyZSBhbmQgZ3JlcCBmaW5kcyBhbGwgdXNhZ2VzLlxuICBNQVhfTkFNRV9MRU5HVEg6IDEwMCwgICAgICAgICAgICAgICAgICAgICAvLyBFbGVtZW50IG5hbWUgZmllbGRcbiAgTUFYX0RFU0NSSVBUSU9OX0xFTkdUSDogNTAwLCAgICAgICAgICAgICAgLy8gRWxlbWVudCBkZXNjcmlwdGlvbiBmaWVsZFxuICBNQVhfRE9DVU1FTlRBVElPTl9GSUVMRF9MRU5HVEg6IDY0ICogMTAyNCwgLy8gTmVzdGVkIGhlbHAvZXhhbXBsZSBkb2NzIGluIFlBTUwvZnJvbnRtYXR0ZXJcbiAgTUFYX0VOVU1fRklFTERfTEVOR1RIOiAyMCwgICAgICAgICAgICAgICAgLy8gU2hvcnQgZW51bS1saWtlIGZpZWxkcyAoc3RyYXRlZ3ksIHJvbGUsIGFjdGl2YXRpb24pXG4gIE1BWF9UQUdfTEVOR1RIOiA1MCwgICAgICAgICAgICAgICAgICAgICAgIC8vIEluZGl2aWR1YWwgdGFnIC8gY2F0ZWdvcnkgdmFsdWVzXG4gIE1BWF9DT01NQU5EX0FSR19MRU5HVEg6IDEwMDAsICAgICAgICAgICAgIC8vIENMSSBjb21tYW5kIGFyZ3VtZW50IHZhbGlkYXRpb25cblxuICAvLyBSZWdleCB2YWxpZGF0aW9uIOKAlCBjb250ZW50IGxlbmd0aCBjYXBzIHBlciBwYXR0ZXJuIGNvbXBsZXhpdHkgdGllci5cbiAgLy8gVGhlc2UgYXJlIHRoZSBkZWZhdWx0cyB1c2VkIGJ5IFJlZ2V4VmFsaWRhdG9yIHdoZW4gbm8gZXhwbGljaXQgbWF4TGVuZ3RoIGlzIHBhc3NlZC5cbiAgLy8gTG93L21lZGl1bSBhcmUgc2FmZSBhdCBNQVhfQ09OVEVOVF9MRU5HVEggYmVjYXVzZSB0aGV5J3JlIE8obikgbGluZWFyIHRpbWUuXG4gIC8vIEhpZ2gtY29tcGxleGl0eSBwYXR0ZXJucyAobmVzdGVkIHF1YW50aWZpZXJzLCBSZURvUyByaXNrKSBhcmUgaGFyZC1jYXBwZWQgYXQgMUtCLlxuICBNQVhfUkVHRVhfSU5QVVRfTEVOR1RIOiAxMDAwMCwgICAgICAgICAgICAvLyBTYWZlUmVnZXggZGVmYXVsdCBmb3IgdXNlci1zdXBwbGllZCBwYXR0ZXJuc1xuXG4gIC8vIFlBTUwgYm9tYiBkZXRlY3Rpb24gdGhyZXNob2xkIChTRUNVUklUWSBGSVggIzEyOTgpXG4gIC8vIE1heGltdW0gYWxsb3dlZCBhbGlhcy10by1hbmNob3IgYW1wbGlmaWNhdGlvbiByYXRpb1xuICAvLyBTZXQgdG8gNToxIC0gYmFsYW5jZXMgc2VjdXJpdHkgKGVhcmx5IERvUyBkZXRlY3Rpb24pIHdpdGggdXNhYmlsaXR5IChsZWdpdGltYXRlIFlBTUwgcGF0dGVybnMpXG4gIC8vIFJhdGlvbmFsZTogTW9zdCBsZWdpdGltYXRlIFlBTUwgdXNlcyDiiaQzw5cgYW1wbGlmaWNhdGlvbjsgNcOXIHByb3ZpZGVzIHNhZmV0eSBtYXJnaW5cbiAgLy8gd2hpbGUgYmxvY2tpbmcgZXhwb25lbnRpYWwgZXhwYW5zaW9uIGF0dGFja3MgdGhhdCB0eXBpY2FsbHkgc3RhcnQgYXQgMTDDlytcbiAgWUFNTF9CT01CX0FNUExJRklDQVRJT05fVEhSRVNIT0xEOiA1XG59O1xuXG4vKiogU2hhcmVkIHNldmVyaXR5IHR5cGUgdXNlZCBhY3Jvc3Mgc2VjdXJpdHkgdmFsaWRhdG9ycyAoIzE3ODItNykgKi9cbmV4cG9ydCB0eXBlIFNlY3VyaXR5U2V2ZXJpdHlMZXZlbCA9ICdsb3cnIHwgJ21lZGl1bScgfCAnaGlnaCcgfCAnY3JpdGljYWwnO1xuXG4vKipcbiAqIEVzY2FsYXRlIHNldmVyaXR5IGxldmVsIOKAlCBoaWdoZXIgc2V2ZXJpdHkgdGFrZXMgcHJlY2VkZW5jZS5cbiAqIEV4dHJhY3RlZCBmcm9tIFVuaWNvZGVWYWxpZGF0b3IgYW5kIElucHV0Tm9ybWFsaXplciB0byBlbGltaW5hdGUgZHVwbGljYXRpb24gKCMxNzgyLTcpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZXNjYWxhdGVTZXZlcml0eShcbiAgY3VycmVudDogU2VjdXJpdHlTZXZlcml0eUxldmVsIHwgdW5kZWZpbmVkLFxuICBuZXdTZXZlcml0eTogU2VjdXJpdHlTZXZlcml0eUxldmVsXG4pOiBTZWN1cml0eVNldmVyaXR5TGV2ZWwge1xuICBjb25zdCBsZXZlbHMgPSB7IGxvdzogMSwgbWVkaXVtOiAyLCBoaWdoOiAzLCBjcml0aWNhbDogNCB9O1xuICBjb25zdCBjdXJyZW50TGV2ZWwgPSBjdXJyZW50ID8gbGV2ZWxzW2N1cnJlbnRdIDogMDtcbiAgcmV0dXJuIGxldmVsc1tuZXdTZXZlcml0eV0gPiBjdXJyZW50TGV2ZWwgPyBuZXdTZXZlcml0eSA6IChjdXJyZW50IHx8ICdsb3cnKTtcbn1cblxuLy8gSW5wdXQgdmFsaWRhdGlvbiBwYXR0ZXJuc1xuZXhwb3J0IGNvbnN0IFZBTElEQVRJT05fUEFUVEVSTlMgPSB7XG4gIFNBRkVfRklMRU5BTUU6IC9eW2EtekEtWjAtOV1bYS16QS1aMC05XFwtXy5dezAsMjUwfVthLXpBLVowLTldJC8sXG4gIFNBRkVfUEFUSDogL15bYS16QS1aMC05Oi9cXC1fLn5dezEsNTAwfSQvLFxuICBTQUZFX1VTRVJOQU1FOiAvXlthLXpBLVowLTldW2EtekEtWjAtOVxcLV8uXXswLDMwfVthLXpBLVowLTldJC8sXG4gIFNBRkVfQ0FURUdPUlk6IC9eW2EtekEtWl1bYS16QS1aMC05XFwtX117MCwyMH0kLyxcbiAgU0FGRV9FTUFJTDogL15bXlxcc0BdezEsNjR9QFteXFxzQF17MSwyNTN9XFwuW15cXHNAXXsxLDYzfSQvLCAgLy8gUkZDIDUzMjEgY29tcGxpYW50IGxpbWl0c1xuXG4gIC8vIEZpZWxkLWFwcHJvcHJpYXRlIHBhdHRlcm5zIGZvciBzYW5pdGl6ZS10aGVuLXZhbGlkYXRlIGFwcHJvYWNoXG4gIC8vIFRoZXNlIHBhdHRlcm5zIHZhbGlkYXRlIEFGVEVSIHNhbml0aXphdGlvbiwgc28gdGhleSBhbGxvdyBsZWdpdGltYXRlIGNoYXJhY3RlcnNcblxuICAvLyBGb3IgbmFtZXM6IGFsbG93IGxldHRlcnMgKGluY2x1ZGluZyBhY2NlbnRlZCBMYXRpbiksIG51bWJlcnMsIHNwYWNlcywgYW5kIGJhc2ljIHB1bmN0dWF0aW9uXG4gIC8vIFVzZXMgVW5pY29kZSBwcm9wZXJ0eSBlc2NhcGVzIGZvciBwcm9wZXIgaW50ZXJuYXRpb25hbCBzdXBwb3J0XG4gIFNBRkVfTkFNRTogL15bXFxwe0x9XFxwe059XFxzXFwtXy5dKyQvdSxcblxuICAvLyBGb3IgZGVzY3JpcHRpb25zOiBhbGxvdyBicm9hZCBwdW5jdHVhdGlvbiBmb3IgcmVhZGFiaWxpdHlcbiAgLy8gSW5jbHVkZXMgY29tbW9uIHN5bWJvbHMgZm91bmQgaW4gcmVhbC13b3JsZCBwb3J0Zm9saW8gZGVzY3JpcHRpb25zOlxuICAvLyAjKEMjL2hhc2h0YWdzKSArKEMrKykgJShwZXJjZW50YWdlcykgPShrZXk9dmFsdWUpIEAoZW1haWwvaGFuZGxlcylcbiAgLy8gJihhbmQpIH4oYXBwcm94aW1hdGUpICooZW1waGFzaXMpIHwoc2VwYXJhdG9ycykge30odGVtcGxhdGVzKVxuICAvLyA8PihhbmdsZSBicmFja2V0cykgJChjdXJyZW5jeSkgXihjYXJldCkgYChiYWNrdGljaylcbiAgLy8g4oaS4oaU4oaQ4oaR4oaTKGFycm93cykg4pyT4pyXKGNoZWNrbWFya3MpIGFuZCBvdGhlciBVbmljb2RlIHN5bWJvbHNcbiAgU0FGRV9ERVNDUklQVElPTjogL15bXFxwe0x9XFxwe059XFxwe1B9XFxwe1N9XFxzQCMkJV4mKis9fmB8XFxcXF0rJC91LFxuXG4gIC8vIEZvciBjb250ZW50OiBtb3N0IHBlcm1pc3NpdmUgLSBDb250ZW50VmFsaWRhdG9yIGhhbmRsZXMgc2VjdXJpdHkgdGhyZWF0c1xuICAvLyBUaGlzIGFsbG93cyBlc3NlbnRpYWxseSBhbnl0aGluZyBzaW5jZSBjb250ZW50IHZhbGlkYXRpb24gaXMgc2VwYXJhdGVcbiAgU0FGRV9DT05URU5UOiAvXltcXHNcXFNdKiQvLFxuXG4gIC8vIEZvciBmaWxlbmFtZXMgaW4gY3JlYXRlIG9wZXJhdGlvbnM6IHN0cmljdCBBU0NJSSBvbmx5IChkaWZmZXJlbnQgZnJvbSBTQUZFX0ZJTEVOQU1FIHdoaWNoIGhhcyBsZW5ndGggbGltaXRzKVxuICBTQUZFX0ZJTEVOQU1FX0NSRUFURTogL15bYS16QS1aMC05XFwtXy5dKyQvXG59O1xuXG4vKipcbiAqIEh1bWFuLXJlYWRhYmxlIGRlc2NyaXB0aW9ucyBmb3IgZWFjaCB2YWxpZGF0aW9uIHBhdHRlcm4uXG4gKiBVc2VkIGJ5IFZhbGlkYXRpb25TZXJ2aWNlIHRvIHByb2R1Y2UgYWN0aW9uYWJsZSBlcnJvciBtZXNzYWdlcy5cbiAqXG4gKiAtIGBhbGxvd2VkYDogc2hvcnQgZGVzY3JpcHRpb24gb2YgdGhlIGNoYXJhY3RlciBzZXRcbiAqIC0gYGNoYXJUZXN0YDogc2luZ2xlLWNoYXJhY3RlciByZWdleCB0byBpZGVudGlmeSB3aGljaCBjaGFycyBhcmUgaW52YWxpZFxuICogLSBgc3RydWN0dXJhbGAgKG9wdGlvbmFsKTogZXh0cmEgY29uc3RyYWludCBub3QgY2FwdHVyZWQgYnkgY2hhclRlc3RcbiAqL1xuZXhwb3J0IGNvbnN0IFBBVFRFUk5fREVTQ1JJUFRJT05TOiBSZWNvcmQ8c3RyaW5nLCB7XG4gIGFsbG93ZWQ6IHN0cmluZztcbiAgY2hhclRlc3Q6IFJlZ0V4cDtcbiAgc3RydWN0dXJhbD86IHN0cmluZztcbn0+ID0ge1xuICBTQUZFX05BTUU6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgc3BhY2VzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cycsXG4gICAgY2hhclRlc3Q6IC9eW1xccHtMfVxccHtOfVxcc1xcLV8uXSQvdSxcbiAgfSxcbiAgU0FGRV9ERVNDUklQVElPTjoge1xuICAgIGFsbG93ZWQ6ICdsZXR0ZXJzLCBudW1iZXJzLCBzeW1ib2xzLCBzcGFjZXMsIGFuZCBjb21tb24gcHVuY3R1YXRpb24nLFxuICAgIGNoYXJUZXN0OiAvXltcXHB7TH1cXHB7Tn1cXHB7UH1cXHB7U31cXHNAIyQlXiYqKz1+YHxcXFxcXSQvdSxcbiAgfSxcbiAgU0FGRV9DT05URU5UOiB7XG4gICAgYWxsb3dlZDogJ2FueSBjaGFyYWN0ZXJzJyxcbiAgICBjaGFyVGVzdDogL15bXFxzXFxTXSQvLFxuICB9LFxuICBTQUZFX0ZJTEVOQU1FX0NSRUFURToge1xuICAgIGFsbG93ZWQ6ICdsZXR0ZXJzLCBudW1iZXJzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cycsXG4gICAgY2hhclRlc3Q6IC9eW2EtekEtWjAtOVxcLV8uXSQvLFxuICB9LFxuICBTQUZFX0ZJTEVOQU1FOiB7XG4gICAgYWxsb3dlZDogJ2xldHRlcnMsIG51bWJlcnMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBkb3RzJyxcbiAgICBjaGFyVGVzdDogL15bYS16QS1aMC05XFwtXy5dJC8sXG4gICAgc3RydWN0dXJhbDogJ211c3Qgc3RhcnQgYW5kIGVuZCB3aXRoIGFscGhhbnVtZXJpYyAobWF4IDI1MiBjaGFycyknLFxuICB9LFxuICBTQUZFX1BBVEg6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgY29sb25zLCBzbGFzaGVzLCBoeXBoZW5zLCB1bmRlcnNjb3JlcywgZG90cywgdGlsZGVzJyxcbiAgICBjaGFyVGVzdDogL15bYS16QS1aMC05Oi9cXC1fLn5dJC8sXG4gIH0sXG4gIFNBRkVfVVNFUk5BTUU6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgaHlwaGVucywgdW5kZXJzY29yZXMsIGRvdHMnLFxuICAgIGNoYXJUZXN0OiAvXlthLXpBLVowLTlcXC1fLl0kLyxcbiAgICBzdHJ1Y3R1cmFsOiAnbXVzdCBzdGFydCBhbmQgZW5kIHdpdGggYWxwaGFudW1lcmljICgzLTMyIGNoYXJzKScsXG4gIH0sXG4gIFNBRkVfQ0FURUdPUlk6IHtcbiAgICBhbGxvd2VkOiAnbGV0dGVycywgbnVtYmVycywgaHlwaGVucywgdW5kZXJzY29yZXMnLFxuICAgIGNoYXJUZXN0OiAvXlthLXpBLVowLTlcXC1fXSQvLFxuICAgIHN0cnVjdHVyYWw6ICdtdXN0IHN0YXJ0IHdpdGggYSBsZXR0ZXIgKG1heCAyMSBjaGFycyknLFxuICB9LFxuICBTQUZFX0VNQUlMOiB7XG4gICAgYWxsb3dlZDogJ2xldHRlcnMsIG51bWJlcnMsIGRvdHMsIGh5cGhlbnMsIHVuZGVyc2NvcmVzLCBAJyxcbiAgICBjaGFyVGVzdDogL15bXlxcc0BdJC8sXG4gIH0sXG59O1xuIl19