@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.
252 lines • 29.6 kB
JavaScript
/**
* Operation Policies
*
* Default permission levels are derived from the operation's endpoint routing:
* - READ → AUTO_APPROVE (read-only, no side effects)
* - CREATE → CONFIRM_SESSION (additive state changes, safe once approved)
* - UPDATE → CONFIRM_SINGLE_USE (modifying existing data, each instance reviewed)
* - DELETE → CONFIRM_SINGLE_USE (destructive, each instance reviewed)
* - EXECUTE → CONFIRM_SINGLE_USE (unpredictable side effects)
*
* OPERATION_POLICY_OVERRIDES contains only operations that deviate from their
* endpoint default — e.g., operations that need stricter policies, special
* canBeElevated flags, or looser defaults than their endpoint implies.
*
* Resolution hierarchy:
* 1. Element policy (Layer 2 — active element allow/confirm/deny lists)
* 2. Explicit override in OPERATION_POLICY_OVERRIDES
* 3. Endpoint default (derived from OperationRouter)
* 4. Secure fallback: CONFIRM_SINGLE_USE for unknown operations
*
* Examples:
*
* activate_element → READ endpoint → AUTO_APPROVE (no override needed)
* Routing to READ is sufficient. No entry in OPERATION_POLICY_OVERRIDES.
*
* create_element → CREATE endpoint → CONFIRM_SESSION (no override needed)
* Endpoint default handles it. First create confirms, rest of session is smooth.
*
* verify_challenge → CREATE endpoint → overridden to AUTO_APPROVE
* On CREATE (default CONFIRM_SESSION) but must be frictionless to avoid
* requiring confirmation to complete a verification flow.
*
* delete_element → DELETE endpoint → CONFIRM_SINGLE_USE + canBeElevated: false
* Matches endpoint default level, but override locks canBeElevated so no
* element policy can silently auto-approve deletions.
*
* record_execution_step → CREATE endpoint → CONFIRM_SESSION (no override needed)
* Moved from EXECUTE to CREATE so it inherits CONFIRM_SESSION, matching
* the polling loop's need for session-level frictionless approval.
*
* A persona with gatekeeper: { confirm: ['create_element'] } → CONFIRM_SESSION
* Element policy (Layer 2) can tighten or loosen within what the operation allows.
* This is a runtime override via element activation, not a code change.
*/
import { PermissionLevel } from '../GatekeeperTypes.js';
import { getRoute, OPERATION_ROUTES } from '../OperationRouter.js';
/**
* Map CRUDE endpoints to their default permission levels.
*
* This is the single source of truth for what each endpoint implies.
* If an operation is routed to READ, it gets AUTO_APPROVE unless overridden.
*/
const ENDPOINT_DEFAULT_LEVELS = {
READ: PermissionLevel.AUTO_APPROVE,
CREATE: PermissionLevel.CONFIRM_SESSION,
UPDATE: PermissionLevel.CONFIRM_SINGLE_USE,
DELETE: PermissionLevel.CONFIRM_SINGLE_USE,
EXECUTE: PermissionLevel.CONFIRM_SINGLE_USE,
};
/**
* Get the default permission level for a CRUDE endpoint.
*
* @param endpoint - The CRUDE endpoint
* @returns The default permission level for that endpoint
*/
export function getEndpointDefaultLevel(endpoint) {
return ENDPOINT_DEFAULT_LEVELS[endpoint];
}
/**
* Explicit policy overrides for operations that deviate from their endpoint default.
*
* Only add entries here when an operation needs:
* - A different permission level than its endpoint implies
* - A canBeElevated: false restriction
* - A specific rationale that differs from the endpoint's general rationale
*
* Operations NOT listed here inherit their permission level from their endpoint.
*/
export const OPERATION_POLICY_OVERRIDES = {
// ===== CREATE endpoint overrides =====
// These are on CREATE (default CONFIRM_SESSION) but need AUTO_APPROVE
verify_challenge: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'Verification flow — must be auto-approved to avoid requiring confirmation to verify',
},
release_deadlock: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'Deadlock relief flow — requires out-of-band verification and must remain reachable even when confirmations are blocked',
canBeElevated: false,
},
beetlejuice_beetlejuice_beetlejuice: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'Test fixture for danger zone verification — must be auto-approved to avoid requiring confirmation to test',
},
// ===== DELETE endpoint overrides =====
// These match the endpoint default (CONFIRM_SINGLE_USE) but need canBeElevated: false
delete_element: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Destructive operation, permanently removes data',
canBeElevated: false,
},
clear: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Destructive operation, clears all memory entries',
canBeElevated: false,
},
clear_github_auth: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Destructive operation, removes authentication credentials',
canBeElevated: false,
},
// ===== EXECUTE endpoint overrides =====
// These are on EXECUTE (default CONFIRM_SINGLE_USE) but need different levels
// Must be auto-approved to avoid infinite confirmation loops
confirm_operation: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'Gatekeeper confirmation flow — must be auto-approved to avoid requiring confirmation to confirm',
},
// Issue #625: CLI-level permission delegation
permission_prompt: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'Permission evaluation flow — must be auto-approved to avoid infinite permission loops',
canBeElevated: false,
},
// Issue #625 Phase 3: CLI approval workflow
approve_cli_permission: {
defaultLevel: PermissionLevel.AUTO_APPROVE,
rationale: 'CLI approval flow — must be auto-approved to avoid requiring confirmation to approve',
canBeElevated: false,
},
// Note: get_execution_state and get_gathered_data moved to READ endpoint —
// they inherit AUTO_APPROVE from the endpoint default, no override needed.
// record_execution_step moved to CREATE endpoint —
// it inherits CONFIRM_SESSION from the endpoint default, no override needed.
// Session-confirmable lifecycle operations (less friction than per-use)
complete_execution: {
defaultLevel: PermissionLevel.CONFIRM_SESSION,
rationale: 'Signals execution completion, part of active execution',
canBeElevated: true,
},
continue_execution: {
defaultLevel: PermissionLevel.CONFIRM_SESSION,
rationale: 'Resumes execution from saved state',
canBeElevated: true,
},
prepare_handoff: {
defaultLevel: PermissionLevel.CONFIRM_SESSION,
rationale: 'Prepares session handoff snapshot, read-heavy with serialization',
canBeElevated: true,
},
// Non-elevatable execute operations (match endpoint default but lock elevation)
execute_agent: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Executes agent with unpredictable side effects',
canBeElevated: false,
},
abort_execution: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Terminates agent execution, rejecting further operations for the goalId',
canBeElevated: false,
},
resume_from_handoff: {
defaultLevel: PermissionLevel.CONFIRM_SINGLE_USE,
rationale: 'Resumes execution from external handoff data, requires validation',
canBeElevated: false,
},
};
/**
* @deprecated Use OPERATION_POLICY_OVERRIDES instead.
* Kept as an alias for backward compatibility with code that imports OPERATION_POLICIES.
*/
export const OPERATION_POLICIES = OPERATION_POLICY_OVERRIDES;
/**
* Get the explicit policy override for an operation, if one exists.
*
* @param operation - The operation name
* @returns The override policy, or undefined if no override exists
*/
export function getOperationPolicy(operation) {
return OPERATION_POLICY_OVERRIDES[operation];
}
/**
* Get the default permission level for an operation.
*
* Resolution order:
* 1. Explicit override in OPERATION_POLICY_OVERRIDES
* 2. Endpoint default from OperationRouter
* 3. CONFIRM_SINGLE_USE for unknown operations (secure fallback)
*
* @param operation - The operation name
* @returns The effective default permission level
*/
export function getDefaultPermissionLevel(operation) {
// 1. Check for explicit override
const override = OPERATION_POLICY_OVERRIDES[operation];
if (override) {
return override.defaultLevel;
}
// 2. Derive from endpoint routing
const route = getRoute(operation);
if (route) {
return ENDPOINT_DEFAULT_LEVELS[route.endpoint];
}
// 3. Secure fallback for unknown operations
return PermissionLevel.CONFIRM_SINGLE_USE;
}
/**
* Check if an operation can have its permission level elevated.
* Some destructive operations cannot be elevated to AUTO_APPROVE.
*
* @param operation - The operation name
* @returns true if the operation can be elevated
*/
export function canOperationBeElevated(operation) {
const override = OPERATION_POLICY_OVERRIDES[operation];
// Default to allowing elevation for operations without explicit overrides
return override?.canBeElevated ?? true;
}
/**
* Get all operations at a specific effective permission level.
* Considers both explicit overrides and endpoint-derived defaults.
*
* @param level - The permission level to filter by
* @returns Array of operation names at that level
*/
export function getOperationsAtLevel(level) {
const results = [];
for (const operation of Object.keys(OPERATION_ROUTES)) {
if (getDefaultPermissionLevel(operation) === level) {
results.push(operation);
}
}
return results;
}
/**
* Get all auto-approved operations.
* These are safe to execute without any confirmation.
*/
export function getAutoApprovedOperations() {
return getOperationsAtLevel(PermissionLevel.AUTO_APPROVE);
}
/**
* Get all operations requiring confirmation.
* These need user approval before execution.
*/
export function getConfirmationRequiredOperations() {
return [
...getOperationsAtLevel(PermissionLevel.CONFIRM_SESSION),
...getOperationsAtLevel(PermissionLevel.CONFIRM_SINGLE_USE),
];
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiT3BlcmF0aW9uUG9saWNpZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvaGFuZGxlcnMvbWNwLWFxbC9wb2xpY2llcy9PcGVyYXRpb25Qb2xpY2llcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJDRztBQUVILE9BQU8sRUFBRSxlQUFlLEVBQXdCLE1BQU0sdUJBQXVCLENBQUM7QUFDOUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBcUIsTUFBTSx1QkFBdUIsQ0FBQztBQUV0Rjs7Ozs7R0FLRztBQUNILE1BQU0sdUJBQXVCLEdBQTBDO0lBQ3JFLElBQUksRUFBRSxlQUFlLENBQUMsWUFBWTtJQUNsQyxNQUFNLEVBQUUsZUFBZSxDQUFDLGVBQWU7SUFDdkMsTUFBTSxFQUFFLGVBQWUsQ0FBQyxrQkFBa0I7SUFDMUMsTUFBTSxFQUFFLGVBQWUsQ0FBQyxrQkFBa0I7SUFDMUMsT0FBTyxFQUFFLGVBQWUsQ0FBQyxrQkFBa0I7Q0FDNUMsQ0FBQztBQUVGOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLFFBQXNCO0lBQzVELE9BQU8sdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7QUFDM0MsQ0FBQztBQUVEOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sQ0FBQyxNQUFNLDBCQUEwQixHQUFvQztJQUN6RSx3Q0FBd0M7SUFDeEMsc0VBQXNFO0lBQ3RFLGdCQUFnQixFQUFFO1FBQ2hCLFlBQVksRUFBRSxlQUFlLENBQUMsWUFBWTtRQUMxQyxTQUFTLEVBQUUscUZBQXFGO0tBQ2pHO0lBQ0QsZ0JBQWdCLEVBQUU7UUFDaEIsWUFBWSxFQUFFLGVBQWUsQ0FBQyxZQUFZO1FBQzFDLFNBQVMsRUFBRSx3SEFBd0g7UUFDbkksYUFBYSxFQUFFLEtBQUs7S0FDckI7SUFDRCxtQ0FBbUMsRUFBRTtRQUNuQyxZQUFZLEVB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T0FBTyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDakQsQ0FBQztJQUVELDRDQUE0QztJQUM1QyxPQUFPLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQztBQUM1QyxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLHNCQUFzQixDQUFDLFNBQWlCO0lBQ3RELE1BQU0sUUFBUSxHQUFHLDBCQUEwQixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZELDBFQUEwRTtJQUMxRSxPQUFPLFFBQVEsRUFBRSxhQUFhLElBQUksSUFBSSxDQUFDO0FBQ3pDLENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsS0FBc0I7SUFDekQsTUFBTSxPQUFPLEdBQWEsRUFBRSxDQUFDO0lBRTdCLEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7UUFDdEQsSUFBSSx5QkFBeUIsQ0FBQyxTQUFTLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQztZQUNuRCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxPQUFPLENBQUM7QUFDakIsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSx5QkFBeUI7SUFDdkMsT0FBTyxvQkFBb0IsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUM7QUFDNUQsQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sVUFBVSxpQ0FBaUM7SUFDL0MsT0FBTztRQUNMLEdBQUcsb0JBQW9CLENBQUMsZUFBZSxDQUFDLGVBQWUsQ0FBQztRQUN4RCxHQUFHLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQztLQUM1RCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3BlcmF0aW9uIFBvbGljaWVzXG4gKlxuICogRGVmYXVsdCBwZXJtaXNzaW9uIGxldmVscyBhcmUgZGVyaXZlZCBmcm9tIHRoZSBvcGVyYXRpb24ncyBlbmRwb2ludCByb3V0aW5nOlxuICogLSBSRUFEICAgIOKGkiBBVVRPX0FQUFJPVkUgKHJlYWQtb25seSwgbm8gc2lkZSBlZmZlY3RzKVxuICogLSBDUkVBVEUgIOKGkiBDT05GSVJNX1NFU1NJT04gKGFkZGl0aXZlIHN0YXRlIGNoYW5nZXMsIHNhZmUgb25jZSBhcHByb3ZlZClcbiAqIC0gVVBEQVRFICDihpIgQ09ORklSTV9TSU5HTEVfVVNFIChtb2RpZnlpbmcgZXhpc3RpbmcgZGF0YSwgZWFjaCBpbnN0YW5jZSByZXZpZXdlZClcbiAqIC0gREVMRVRFICDihpIgQ09ORklSTV9TSU5HTEVfVVNFIChkZXN0cnVjdGl2ZSwgZWFjaCBpbnN0YW5jZSByZXZpZXdlZClcbiAqIC0gRVhFQ1VURSDihpIgQ09ORklSTV9TSU5HTEVfVVNFICh1bnByZWRpY3RhYmxlIHNpZGUgZWZmZWN0cylcbiAqXG4gKiBPUEVSQVRJT05fUE9MSUNZX09WRVJSSURFUyBjb250YWlucyBvbmx5IG9wZXJhdGlvbnMgdGhhdCBkZXZpYXRlIGZyb20gdGhlaXJcbiAqIGVuZHBvaW50IGRlZmF1bHQg4oCUIGUuZy4sIG9wZXJhdGlvbnMgdGhhdCBuZWVkIHN0cmljdGVyIHBvbGljaWVzLCBzcGVjaWFsXG4gKiBjYW5CZUVsZXZhdGVkIGZsYWdzLCBvciBsb29zZXIgZGVmYXVsdHMgdGhhbiB0aGVpciBlbmRwb2ludCBpbXBsaWVzLlxuICpcbiAqIFJlc29sdXRpb24gaGllcmFyY2h5OlxuICogMS4gRWxlbWVudCBwb2xpY3kgKExheWVyIDIg4oCUIGFjdGl2ZSBlbGVtZW50IGFsbG93L2NvbmZpcm0vZGVueSBsaXN0cylcbiAqIDIuIEV4cGxpY2l0IG92ZXJyaWRlIGluIE9QRVJBVElPTl9QT0xJQ1lfT1ZFUlJJREVTXG4gKiAzLiBFbmRwb2ludCBkZWZhdWx0IChkZXJpdmVkIGZyb20gT3BlcmF0aW9uUm91dGVyKVxuICogNC4gU2VjdXJlIGZhbGxiYWNrOiBDT05GSVJNX1NJTkdMRV9VU0UgZm9yIHVua25vd24gb3BlcmF0aW9uc1xuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgYWN0aXZhdGVfZWxlbWVudCDihpIgUkVBRCBlbmRwb2ludCDihpIgQVVUT19BUFBST1ZFIChubyBvdmVycmlkZSBuZWVkZWQpXG4gKiAgICAgUm91dGluZyB0byBSRUFEIGlzIHN1ZmZpY2llbnQuIE5vIGVudHJ5IGluIE9QRVJBVElPTl9QT0xJQ1lfT1ZFUlJJREVTLlxuICpcbiAqICAgY3JlYXRlX2VsZW1lbnQg4oaSIENSRUFURSBlbmRwb2ludCDihpIgQ09ORklSTV9TRVNTSU9OIChubyBvdmVycmlkZSBuZWVkZWQpXG4gKiAgICAgRW5kcG9pbnQgZGVmYXVsdCBoYW5kbGVzIGl0LiBGaXJzdCBjcmVhdGUgY29uZmlybXMsIHJlc3Qgb2Ygc2Vzc2lvbiBpcyBzbW9vdGguXG4gKlxuICogICB2ZXJpZnlfY2hhbGxlbmdlIOKGkiBDUkVBVEUgZW5kcG9pbnQg4oaSIG92ZXJyaWRkZW4gdG8gQVVUT19BUFBST1ZFXG4gKiAgICAgT24gQ1JFQVRFIChkZWZhdWx0IENPTkZJUk1fU0VTU0lPTikgYnV0IG11c3QgYmUgZnJpY3Rpb25sZXNzIHRvIGF2b2lkXG4gKiAgICAgcmVxdWlyaW5nIGNvbmZpcm1hdGlvbiB0byBjb21wbGV0ZSBhIHZlcmlmaWNhdGlvbiBmbG93LlxuICpcbiAqICAgZGVsZXRlX2VsZW1lbnQg4oaSIERFTEVURSBlbmRwb2ludCDihpIgQ09ORklSTV9TSU5HTEVfVVNFICsgY2FuQmVFbGV2YXRlZDogZmFsc2VcbiAqICAgICBNYXRjaGVzIGVuZHBvaW50IGRlZmF1bHQgbGV2ZWwsIGJ1dCBvdmVycmlkZSBsb2NrcyBjYW5CZUVsZXZhdGVkIHNvIG5vXG4gKiAgICAgZWxlbWVudCBwb2xpY3kgY2FuIHNpbGVudGx5IGF1dG8tYXBwcm92ZSBkZWxldGlvbnMuXG4gKlxuICogICByZWNvcmRfZXhlY3V0aW9uX3N0ZXAg4oaSIENSRUFURSBlbmRwb2ludCDihpIgQ09ORklSTV9TRVNTSU9OIChubyBvdmVycmlkZSBuZWVkZWQpXG4gKiAgICAgTW92ZWQgZnJvbSBFWEVDVVRFIHRvIENSRUFURSBzbyBpdCBpbmhlcml0cyBDT05GSVJNX1NFU1NJT04sIG1hdGNoaW5nXG4gKiAgICAgdGhlIHBvbGxpbmcgbG9vcCdzIG5lZWQgZm9yIHNlc3Npb24tbGV2ZWwgZnJpY3Rpb25sZXNzIGFwcHJvdmFsLlxuICpcbiAqICAgQSBwZXJzb25hIHdpdGggZ2F0ZWtlZXBlcjogeyBjb25maXJtOiBbJ2NyZWF0ZV9lbGVtZW50J10gfSDihpIgQ09ORklSTV9TRVNTSU9OXG4gKiAgICAgRWxlbWVudCBwb2xpY3kgKExheWVyIDIpIGNhbiB0aWdodGVuIG9yIGxvb3NlbiB3aXRoaW4gd2hhdCB0aGUgb3BlcmF0aW9uIGFsbG93cy5cbiAqICAgICBUaGlzIGlzIGEgcnVudGltZSBvdmVycmlkZSB2aWEgZWxlbWVudCBhY3RpdmF0aW9uLCBub3QgYSBjb2RlIGNoYW5nZS5cbiAqL1xuXG5pbXBvcnQgeyBQZXJtaXNzaW9uTGV2ZWwsIHR5cGUgT3BlcmF0aW9uUG9saWN5IH0gZnJvbSAnLi4vR2F0ZWtlZXBlclR5cGVzLmpzJztcbmltcG9ydCB7IGdldFJvdXRlLCBPUEVSQVRJT05fUk9VVEVTLCB0eXBlIENSVURFbmRwb2ludCB9IGZyb20gJy4uL09wZXJhdGlvblJvdXRlci5qcyc7XG5cbi8qKlxuICogTWFwIENSVURFIGVuZHBvaW50cyB0byB0aGVpciBkZWZhdWx0IHBlcm1pc3Npb24gbGV2ZWxzLlxuICpcbiAqIFRoaXMgaXMgdGhlIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIHdoYXQgZWFjaCBlbmRwb2ludCBpbXBsaWVzLlxuICogSWYgYW4gb3BlcmF0aW9uIGlzIHJvdXRlZCB0byBSRUFELCBpdCBnZXRzIEFVVE9fQVBQUk9WRSB1bmxlc3Mgb3ZlcnJpZGRlbi5cbiAqL1xuY29uc3QgRU5EUE9JTlRfREVGQVVMVF9MRVZFTFM6IFJlY29yZDxDUlVERW5kcG9pbnQsIFBlcm1pc3Npb25MZXZlbD4gPSB7XG4gIFJFQUQ6IFBlcm1pc3Npb25MZXZlbC5BVVRPX0FQUFJPVkUsXG4gIENSRUFURTogUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0VTU0lPTixcbiAgVVBEQVRFOiBQZXJtaXNzaW9uTGV2ZWwuQ09ORklSTV9TSU5HTEVfVVNFLFxuICBERUxFVEU6IFBlcm1pc3Npb25MZXZlbC5DT05GSVJNX1NJTkdMRV9VU0UsXG4gIEVYRUNVVEU6IFBlcm1pc3Npb25MZXZlbC5DT05GSVJNX1NJTkdMRV9VU0UsXG59O1xuXG4vKipcbiAqIEdldCB0aGUgZGVmYXVsdCBwZXJtaXNzaW9uIGxldmVsIGZvciBhIENSVURFIGVuZHBvaW50LlxuICpcbiAqIEBwYXJhbSBlbmRwb2ludCAtIFRoZSBDUlVERSBlbmRwb2ludFxuICogQHJldHVybnMgVGhlIGRlZmF1bHQgcGVybWlzc2lvbiBsZXZlbCBmb3IgdGhhdCBlbmRwb2ludFxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW5kcG9pbnREZWZhdWx0TGV2ZWwoZW5kcG9pbnQ6IENSVURFbmRwb2ludCk6IFBlcm1pc3Npb25MZXZlbCB7XG4gIHJldHVybiBFTkRQT0lOVF9ERUZBVUxUX0xFVkVMU1tlbmRwb2ludF07XG59XG5cbi8qKlxuICogRXhwbGljaXQgcG9saWN5IG92ZXJyaWRlcyBmb3Igb3BlcmF0aW9ucyB0aGF0IGRldmlhdGUgZnJvbSB0aGVpciBlbmRwb2ludCBkZWZhdWx0LlxuICpcbiAqIE9ubHkgYWRkIGVudHJpZXMgaGVyZSB3aGVuIGFuIG9wZXJhdGlvbiBuZWVkczpcbiAqIC0gQSBkaWZmZXJlbnQgcGVybWlzc2lvbiBsZXZlbCB0aGFuIGl0cyBlbmRwb2ludCBpbXBsaWVzXG4gKiAtIEEgY2FuQmVFbGV2YXRlZDogZmFsc2UgcmVzdHJpY3Rpb25cbiAqIC0gQSBzcGVjaWZpYyByYXRpb25hbGUgdGhhdCBkaWZmZXJzIGZyb20gdGhlIGVuZHBvaW50J3MgZ2VuZXJhbCByYXRpb25hbGVcbiAqXG4gKiBPcGVyYXRpb25zIE5PVCBsaXN0ZWQgaGVyZSBpbmhlcml0IHRoZWlyIHBlcm1pc3Npb24gbGV2ZWwgZnJvbSB0aGVpciBlbmRwb2ludC5cbiAqL1xuZXhwb3J0IGNvbnN0IE9QRVJBVElPTl9QT0xJQ1lfT1ZFUlJJREVTOiBSZWNvcmQ8c3RyaW5nLCBPcGVyYXRpb25Qb2xpY3k+ID0ge1xuICAvLyA9PT09PSBDUkVBVEUgZW5kcG9pbnQgb3ZlcnJpZGVzID09PT09XG4gIC8vIFRoZXNlIGFyZSBvbiBDUkVBVEUgKGRlZmF1bHQgQ09ORklSTV9TRVNTSU9OKSBidXQgbmVlZCBBVVRPX0FQUFJPVkVcbiAgdmVyaWZ5X2NoYWxsZW5nZToge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSxcbiAgICByYXRpb25hbGU6ICdWZXJpZmljYXRpb24gZmxvdyDigJQgbXVzdCBiZSBhdXRvLWFwcHJvdmVkIHRvIGF2b2lkIHJlcXVpcmluZyBjb25maXJtYXRpb24gdG8gdmVyaWZ5JyxcbiAgfSxcbiAgcmVsZWFzZV9kZWFkbG9jazoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSxcbiAgICByYXRpb25hbGU6ICdEZWFkbG9jayByZWxpZWYgZmxvdyDigJQgcmVxdWlyZXMgb3V0LW9mLWJhbmQgdmVyaWZpY2F0aW9uIGFuZCBtdXN0IHJlbWFpbiByZWFjaGFibGUgZXZlbiB3aGVuIGNvbmZpcm1hdGlvbnMgYXJlIGJsb2NrZWQnLFxuICAgIGNhbkJlRWxldmF0ZWQ6IGZhbHNlLFxuICB9LFxuICBiZWV0bGVqdWljZV9iZWV0bGVqdWljZV9iZWV0bGVqdWljZToge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSxcbiAgICByYXRpb25hbGU6ICdUZXN0IGZpeHR1cmUgZm9yIGRhbmdlciB6b25lIHZlcmlmaWNhdGlvbiDigJQgbXVzdCBiZSBhdXRvLWFwcHJvdmVkIHRvIGF2b2lkIHJlcXVpcmluZyBjb25maXJtYXRpb24gdG8gdGVzdCcsXG4gIH0sXG5cbiAgLy8gPT09PT0gREVMRVRFIGVuZHBvaW50IG92ZXJyaWRlcyA9PT09PVxuICAvLyBUaGVzZSBtYXRjaCB0aGUgZW5kcG9pbnQgZGVmYXVsdCAoQ09ORklSTV9TSU5HTEVfVVNFKSBidXQgbmVlZCBjYW5CZUVsZXZhdGVkOiBmYWxzZVxuICBkZWxldGVfZWxlbWVudDoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0lOR0xFX1VTRSxcbiAgICByYXRpb25hbGU6ICdEZXN0cnVjdGl2ZSBvcGVyYXRpb24sIHBlcm1hbmVudGx5IHJlbW92ZXMgZGF0YScsXG4gICAgY2FuQmVFbGV2YXRlZDogZmFsc2UsXG4gIH0sXG4gIGNsZWFyOiB7XG4gICAgZGVmYXVsdExldmVsOiBQZXJtaXNzaW9uTGV2ZWwuQ09ORklSTV9TSU5HTEVfVVNFLFxuICAgIHJhdGlvbmFsZTogJ0Rlc3RydWN0aXZlIG9wZXJhdGlvbiwgY2xlYXJzIGFsbCBtZW1vcnkgZW50cmllcycsXG4gICAgY2FuQmVFbGV2YXRlZDogZmFsc2UsXG4gIH0sXG4gIGNsZWFyX2dpdGh1Yl9hdXRoOiB7XG4gICAgZGVmYXVsdExldmVsOiBQZXJtaXNzaW9uTGV2ZWwuQ09ORklSTV9TSU5HTEVfVVNFLFxuICAgIHJhdGlvbmFsZTogJ0Rlc3RydWN0aXZlIG9wZXJhdGlvbiwgcmVtb3ZlcyBhdXRoZW50aWNhdGlvbiBjcmVkZW50aWFscycsXG4gICAgY2FuQmVFbGV2YXRlZDogZmFsc2UsXG4gIH0sXG5cbiAgLy8gPT09PT0gRVhFQ1VURSBlbmRwb2ludCBvdmVycmlkZXMgPT09PT1cbiAgLy8gVGhlc2UgYXJlIG9uIEVYRUNVVEUgKGRlZmF1bHQgQ09ORklSTV9TSU5HTEVfVVNFKSBidXQgbmVlZCBkaWZmZXJlbnQgbGV2ZWxzXG5cbiAgLy8gTXVzdCBiZSBhdXRvLWFwcHJvdmVkIHRvIGF2b2lkIGluZmluaXRlIGNvbmZpcm1hdGlvbiBsb29wc1xuICBjb25maXJtX29wZXJhdGlvbjoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSxcbiAgICByYXRpb25hbGU6ICdHYXRla2VlcGVyIGNvbmZpcm1hdGlvbiBmbG93IOKAlCBtdXN0IGJlIGF1dG8tYXBwcm92ZWQgdG8gYXZvaWQgcmVxdWlyaW5nIGNvbmZpcm1hdGlvbiB0byBjb25maXJtJyxcbiAgfSxcbiAgLy8gSXNzdWUgIzYyNTogQ0xJLWxldmVsIHBlcm1pc3Npb24gZGVsZWdhdGlvblxuICBwZXJtaXNzaW9uX3Byb21wdDoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSxcbiAgICByYXRpb25hbGU6ICdQZXJtaXNzaW9uIGV2YWx1YXRpb24gZmxvdyDigJQgbXVzdCBiZSBhdXRvLWFwcHJvdmVkIHRvIGF2b2lkIGluZmluaXRlIHBlcm1pc3Npb24gbG9vcHMnLFxuICAgIGNhbkJlRWxldmF0ZWQ6IGZhbHNlLFxuICB9LFxuICAvLyBJc3N1ZSAjNjI1IFBoYXNlIDM6IENMSSBhcHByb3ZhbCB3b3JrZmxvd1xuICBhcHByb3ZlX2NsaV9wZXJtaXNzaW9uOiB7XG4gICAgZGVmYXVsdExldmVsOiBQZXJtaXNzaW9uTGV2ZWwuQVVUT19BUFBST1ZFLFxuICAgIHJhdGlvbmFsZTogJ0NMSSBhcHByb3ZhbCBmbG93IOKAlCBtdXN0IGJlIGF1dG8tYXBwcm92ZWQgdG8gYXZvaWQgcmVxdWlyaW5nIGNvbmZpcm1hdGlvbiB0byBhcHByb3ZlJyxcbiAgICBjYW5CZUVsZXZhdGVkOiBmYWxzZSxcbiAgfSxcblxuICAvLyBOb3RlOiBnZXRfZXhlY3V0aW9uX3N0YXRlIGFuZCBnZXRfZ2F0aGVyZWRfZGF0YSBtb3ZlZCB0byBSRUFEIGVuZHBvaW50IOKAlFxuICAvLyB0aGV5IGluaGVyaXQgQVVUT19BUFBST1ZFIGZyb20gdGhlIGVuZHBvaW50IGRlZmF1bHQsIG5vIG92ZXJyaWRlIG5lZWRlZC5cbiAgLy8gcmVjb3JkX2V4ZWN1dGlvbl9zdGVwIG1vdmVkIHRvIENSRUFURSBlbmRwb2ludCDigJRcbiAgLy8gaXQgaW5oZXJpdHMgQ09ORklSTV9TRVNTSU9OIGZyb20gdGhlIGVuZHBvaW50IGRlZmF1bHQsIG5vIG92ZXJyaWRlIG5lZWRlZC5cblxuICAvLyBTZXNzaW9uLWNvbmZpcm1hYmxlIGxpZmVjeWNsZSBvcGVyYXRpb25zIChsZXNzIGZyaWN0aW9uIHRoYW4gcGVyLXVzZSlcbiAgY29tcGxldGVfZXhlY3V0aW9uOiB7XG4gICAgZGVmYXVsdExldmVsOiBQZXJtaXNzaW9uTGV2ZWwuQ09ORklSTV9TRVNTSU9OLFxuICAgIHJhdGlvbmFsZTogJ1NpZ25hbHMgZXhlY3V0aW9uIGNvbXBsZXRpb24sIHBhcnQgb2YgYWN0aXZlIGV4ZWN1dGlvbicsXG4gICAgY2FuQmVFbGV2YXRlZDogdHJ1ZSxcbiAgfSxcbiAgY29udGludWVfZXhlY3V0aW9uOiB7XG4gICAgZGVmYXVsdExldmVsOiBQZXJtaXNzaW9uTGV2ZWwuQ09ORklSTV9TRVNTSU9OLFxuICAgIHJhdGlvbmFsZTogJ1Jlc3VtZXMgZXhlY3V0aW9uIGZyb20gc2F2ZWQgc3RhdGUnLFxuICAgIGNhbkJlRWxldmF0ZWQ6IHRydWUsXG4gIH0sXG4gIHByZXBhcmVfaGFuZG9mZjoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0VTU0lPTixcbiAgICByYXRpb25hbGU6ICdQcmVwYXJlcyBzZXNzaW9uIGhhbmRvZmYgc25hcHNob3QsIHJlYWQtaGVhdnkgd2l0aCBzZXJpYWxpemF0aW9uJyxcbiAgICBjYW5CZUVsZXZhdGVkOiB0cnVlLFxuICB9LFxuXG4gIC8vIE5vbi1lbGV2YXRhYmxlIGV4ZWN1dGUgb3BlcmF0aW9ucyAobWF0Y2ggZW5kcG9pbnQgZGVmYXVsdCBidXQgbG9jayBlbGV2YXRpb24pXG4gIGV4ZWN1dGVfYWdlbnQ6IHtcbiAgICBkZWZhdWx0TGV2ZWw6IFBlcm1pc3Npb25MZXZlbC5DT05GSVJNX1NJTkdMRV9VU0UsXG4gICAgcmF0aW9uYWxlOiAnRXhlY3V0ZXMgYWdlbnQgd2l0aCB1bnByZWRpY3RhYmxlIHNpZGUgZWZmZWN0cycsXG4gICAgY2FuQmVFbGV2YXRlZDogZmFsc2UsXG4gIH0sXG4gIGFib3J0X2V4ZWN1dGlvbjoge1xuICAgIGRlZmF1bHRMZXZlbDogUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0lOR0xFX1VTRSxcbiAgICByYXRpb25hbGU6ICdUZXJtaW5hdGVzIGFnZW50IGV4ZWN1dGlvbiwgcmVqZWN0aW5nIGZ1cnRoZXIgb3BlcmF0aW9ucyBmb3IgdGhlIGdvYWxJZCcsXG4gICAgY2FuQmVFbGV2YXRlZDogZmFsc2UsXG4gIH0sXG4gIHJlc3VtZV9mcm9tX2hhbmRvZmY6IHtcbiAgICBkZWZhdWx0TGV2ZWw6IFBlcm1pc3Npb25MZXZlbC5DT05GSVJNX1NJTkdMRV9VU0UsXG4gICAgcmF0aW9uYWxlOiAnUmVzdW1lcyBleGVjdXRpb24gZnJvbSBleHRlcm5hbCBoYW5kb2ZmIGRhdGEsIHJlcXVpcmVzIHZhbGlkYXRpb24nLFxuICAgIGNhbkJlRWxldmF0ZWQ6IGZhbHNlLFxuICB9LFxufTtcblxuLyoqXG4gKiBAZGVwcmVjYXRlZCBVc2UgT1BFUkFUSU9OX1BPTElDWV9PVkVSUklERVMgaW5zdGVhZC5cbiAqIEtlcHQgYXMgYW4gYWxpYXMgZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgd2l0aCBjb2RlIHRoYXQgaW1wb3J0cyBPUEVSQVRJT05fUE9MSUNJRVMuXG4gKi9cbmV4cG9ydCBjb25zdCBPUEVSQVRJT05fUE9MSUNJRVMgPSBPUEVSQVRJT05fUE9MSUNZX09WRVJSSURFUztcblxuLyoqXG4gKiBHZXQgdGhlIGV4cGxpY2l0IHBvbGljeSBvdmVycmlkZSBmb3IgYW4gb3BlcmF0aW9uLCBpZiBvbmUgZXhpc3RzLlxuICpcbiAqIEBwYXJhbSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIG5hbWVcbiAqIEByZXR1cm5zIFRoZSBvdmVycmlkZSBwb2xpY3ksIG9yIHVuZGVmaW5lZCBpZiBubyBvdmVycmlkZSBleGlzdHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9wZXJhdGlvblBvbGljeShvcGVyYXRpb246IHN0cmluZyk6IE9wZXJhdGlvblBvbGljeSB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBPUEVSQVRJT05fUE9MSUNZX09WRVJSSURFU1tvcGVyYXRpb25dO1xufVxuXG4vKipcbiAqIEdldCB0aGUgZGVmYXVsdCBwZXJtaXNzaW9uIGxldmVsIGZvciBhbiBvcGVyYXRpb24uXG4gKlxuICogUmVzb2x1dGlvbiBvcmRlcjpcbiAqIDEuIEV4cGxpY2l0IG92ZXJyaWRlIGluIE9QRVJBVElPTl9QT0xJQ1lfT1ZFUlJJREVTXG4gKiAyLiBFbmRwb2ludCBkZWZhdWx0IGZyb20gT3BlcmF0aW9uUm91dGVyXG4gKiAzLiBDT05GSVJNX1NJTkdMRV9VU0UgZm9yIHVua25vd24gb3BlcmF0aW9ucyAoc2VjdXJlIGZhbGxiYWNrKVxuICpcbiAqIEBwYXJhbSBvcGVyYXRpb24gLSBUaGUgb3BlcmF0aW9uIG5hbWVcbiAqIEByZXR1cm5zIFRoZSBlZmZlY3RpdmUgZGVmYXVsdCBwZXJtaXNzaW9uIGxldmVsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXREZWZhdWx0UGVybWlzc2lvbkxldmVsKG9wZXJhdGlvbjogc3RyaW5nKTogUGVybWlzc2lvbkxldmVsIHtcbiAgLy8gMS4gQ2hlY2sgZm9yIGV4cGxpY2l0IG92ZXJyaWRlXG4gIGNvbnN0IG92ZXJyaWRlID0gT1BFUkFUSU9OX1BPTElDWV9PVkVSUklERVNbb3BlcmF0aW9uXTtcbiAgaWYgKG92ZXJyaWRlKSB7XG4gICAgcmV0dXJuIG92ZXJyaWRlLmRlZmF1bHRMZXZlbDtcbiAgfVxuXG4gIC8vIDIuIERlcml2ZSBmcm9tIGVuZHBvaW50IHJvdXRpbmdcbiAgY29uc3Qgcm91dGUgPSBnZXRSb3V0ZShvcGVyYXRpb24pO1xuICBpZiAocm91dGUpIHtcbiAgICByZXR1cm4gRU5EUE9JTlRfREVGQVVMVF9MRVZFTFNbcm91dGUuZW5kcG9pbnRdO1xuICB9XG5cbiAgLy8gMy4gU2VjdXJlIGZhbGxiYWNrIGZvciB1bmtub3duIG9wZXJhdGlvbnNcbiAgcmV0dXJuIFBlcm1pc3Npb25MZXZlbC5DT05GSVJNX1NJTkdMRV9VU0U7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYW4gb3BlcmF0aW9uIGNhbiBoYXZlIGl0cyBwZXJtaXNzaW9uIGxldmVsIGVsZXZhdGVkLlxuICogU29tZSBkZXN0cnVjdGl2ZSBvcGVyYXRpb25zIGNhbm5vdCBiZSBlbGV2YXRlZCB0byBBVVRPX0FQUFJPVkUuXG4gKlxuICogQHBhcmFtIG9wZXJhdGlvbiAtIFRoZSBvcGVyYXRpb24gbmFtZVxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgb3BlcmF0aW9uIGNhbiBiZSBlbGV2YXRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gY2FuT3BlcmF0aW9uQmVFbGV2YXRlZChvcGVyYXRpb246IHN0cmluZyk6IGJvb2xlYW4ge1xuICBjb25zdCBvdmVycmlkZSA9IE9QRVJBVElPTl9QT0xJQ1lfT1ZFUlJJREVTW29wZXJhdGlvbl07XG4gIC8vIERlZmF1bHQgdG8gYWxsb3dpbmcgZWxldmF0aW9uIGZvciBvcGVyYXRpb25zIHdpdGhvdXQgZXhwbGljaXQgb3ZlcnJpZGVzXG4gIHJldHVybiBvdmVycmlkZT8uY2FuQmVFbGV2YXRlZCA/PyB0cnVlO1xufVxuXG4vKipcbiAqIEdldCBhbGwgb3BlcmF0aW9ucyBhdCBhIHNwZWNpZmljIGVmZmVjdGl2ZSBwZXJtaXNzaW9uIGxldmVsLlxuICogQ29uc2lkZXJzIGJvdGggZXhwbGljaXQgb3ZlcnJpZGVzIGFuZCBlbmRwb2ludC1kZXJpdmVkIGRlZmF1bHRzLlxuICpcbiAqIEBwYXJhbSBsZXZlbCAtIFRoZSBwZXJtaXNzaW9uIGxldmVsIHRvIGZpbHRlciBieVxuICogQHJldHVybnMgQXJyYXkgb2Ygb3BlcmF0aW9uIG5hbWVzIGF0IHRoYXQgbGV2ZWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9wZXJhdGlvbnNBdExldmVsKGxldmVsOiBQZXJtaXNzaW9uTGV2ZWwpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IHJlc3VsdHM6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChjb25zdCBvcGVyYXRpb24gb2YgT2JqZWN0LmtleXMoT1BFUkFUSU9OX1JPVVRFUykpIHtcbiAgICBpZiAoZ2V0RGVmYXVsdFBlcm1pc3Npb25MZXZlbChvcGVyYXRpb24pID09PSBsZXZlbCkge1xuICAgICAgcmVzdWx0cy5wdXNoKG9wZXJhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbi8qKlxuICogR2V0IGFsbCBhdXRvLWFwcHJvdmVkIG9wZXJhdGlvbnMuXG4gKiBUaGVzZSBhcmUgc2FmZSB0byBleGVjdXRlIHdpdGhvdXQgYW55IGNvbmZpcm1hdGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEF1dG9BcHByb3ZlZE9wZXJhdGlvbnMoKTogc3RyaW5nW10ge1xuICByZXR1cm4gZ2V0T3BlcmF0aW9uc0F0TGV2ZWwoUGVybWlzc2lvbkxldmVsLkFVVE9fQVBQUk9WRSk7XG59XG5cbi8qKlxuICogR2V0IGFsbCBvcGVyYXRpb25zIHJlcXVpcmluZyBjb25maXJtYXRpb24uXG4gKiBUaGVzZSBuZWVkIHVzZXIgYXBwcm92YWwgYmVmb3JlIGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpcm1hdGlvblJlcXVpcmVkT3BlcmF0aW9ucygpOiBzdHJpbmdbXSB7XG4gIHJldHVybiBbXG4gICAgLi4uZ2V0T3BlcmF0aW9uc0F0TGV2ZWwoUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0VTU0lPTiksXG4gICAgLi4uZ2V0T3BlcmF0aW9uc0F0TGV2ZWwoUGVybWlzc2lvbkxldmVsLkNPTkZJUk1fU0lOR0xFX1VTRSksXG4gIF07XG59XG4iXX0=