@cdklabs/cdk-appmod-catalog-blueprints 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/.jsii +8644 -0
  2. package/LICENSE +202 -0
  3. package/README.md +212 -0
  4. package/lib/document-processing/agentic-document-processing.d.ts +16 -0
  5. package/lib/document-processing/agentic-document-processing.js +90 -0
  6. package/lib/document-processing/base-document-processing.d.ts +189 -0
  7. package/lib/document-processing/base-document-processing.js +509 -0
  8. package/lib/document-processing/bedrock-document-processing.d.ts +167 -0
  9. package/lib/document-processing/bedrock-document-processing.js +297 -0
  10. package/lib/document-processing/index.d.ts +3 -0
  11. package/lib/document-processing/index.js +20 -0
  12. package/lib/document-processing/resources/default-bedrock-invoke/index.py +63 -0
  13. package/lib/document-processing/resources/default-bedrock-invoke/requirements.txt +4 -0
  14. package/lib/document-processing/resources/default-doc-retrieval-lambda/index.mjs +92 -0
  15. package/lib/document-processing/resources/default-doc-retrieval-lambda/package.json +10 -0
  16. package/lib/document-processing/resources/default-error-handler/index.js +46 -0
  17. package/lib/document-processing/resources/default-error-handler/package.json +4 -0
  18. package/lib/document-processing/resources/default-image-processor/classifier.mjs +665 -0
  19. package/lib/document-processing/resources/default-image-processor/extractors.mjs +465 -0
  20. package/lib/document-processing/resources/default-image-processor/index.mjs +143 -0
  21. package/lib/document-processing/resources/default-image-processor/package-lock.json +12 -0
  22. package/lib/document-processing/resources/default-image-processor/package.json +4 -0
  23. package/lib/document-processing/resources/default-image-validator/index.mjs +76 -0
  24. package/lib/document-processing/resources/default-image-validator/package-lock.json +154 -0
  25. package/lib/document-processing/resources/default-image-validator/package.json +7 -0
  26. package/lib/document-processing/resources/default-pdf-processor/index.js +46 -0
  27. package/lib/document-processing/resources/default-pdf-validator/index.js +36 -0
  28. package/lib/document-processing/resources/default-sqs-consumer/index.py +111 -0
  29. package/lib/document-processing/resources/default-sqs-consumer/requirements.txt +4 -0
  30. package/lib/document-processing/resources/default-sqs-consumer/sample_payload.json +20 -0
  31. package/lib/document-processing/resources/default-sqs-consumer/sample_payload_multi.json +24 -0
  32. package/lib/document-processing/resources/default-strands-agent/index.py +111 -0
  33. package/lib/document-processing/resources/default-strands-agent/requirements.txt +6 -0
  34. package/lib/document-processing/tests/agentic-document-processing-nag.test.d.ts +1 -0
  35. package/lib/document-processing/tests/agentic-document-processing-nag.test.js +107 -0
  36. package/lib/document-processing/tests/agentic-document-processing.test.d.ts +1 -0
  37. package/lib/document-processing/tests/agentic-document-processing.test.js +125 -0
  38. package/lib/document-processing/tests/bedrock-document-processing-nag.test.d.ts +1 -0
  39. package/lib/document-processing/tests/bedrock-document-processing-nag.test.js +101 -0
  40. package/lib/document-processing/tests/bedrock-document-processing.test.d.ts +1 -0
  41. package/lib/document-processing/tests/bedrock-document-processing.test.js +79 -0
  42. package/lib/framework/custom-resource/default-runtimes.d.ts +21 -0
  43. package/lib/framework/custom-resource/default-runtimes.js +34 -0
  44. package/lib/framework/custom-resource/index.d.ts +1 -0
  45. package/lib/framework/custom-resource/index.js +18 -0
  46. package/lib/framework/foundation/access-log.d.ts +69 -0
  47. package/lib/framework/foundation/access-log.js +121 -0
  48. package/lib/framework/foundation/eventbridge-broker.d.ts +18 -0
  49. package/lib/framework/foundation/eventbridge-broker.js +42 -0
  50. package/lib/framework/foundation/index.d.ts +3 -0
  51. package/lib/framework/foundation/index.js +20 -0
  52. package/lib/framework/foundation/network.d.ts +19 -0
  53. package/lib/framework/foundation/network.js +83 -0
  54. package/lib/framework/index.d.ts +2 -0
  55. package/lib/framework/index.js +19 -0
  56. package/lib/framework/quickstart/base-quickstart.d.ts +30 -0
  57. package/lib/framework/quickstart/base-quickstart.js +30 -0
  58. package/lib/index.d.ts +4 -0
  59. package/lib/index.js +21 -0
  60. package/lib/tsconfig.tsbuildinfo +1 -0
  61. package/lib/utilities/cdk-nag-config.d.ts +42 -0
  62. package/lib/utilities/cdk-nag-config.js +194 -0
  63. package/lib/utilities/data-loader-lambda/index.py +282 -0
  64. package/lib/utilities/data-loader-lambda/requirements.txt +3 -0
  65. package/lib/utilities/data-loader.d.ts +173 -0
  66. package/lib/utilities/data-loader.js +447 -0
  67. package/lib/utilities/index.d.ts +3 -0
  68. package/lib/utilities/index.js +20 -0
  69. package/lib/utilities/lambda-iam-utils.d.ts +145 -0
  70. package/lib/utilities/lambda-iam-utils.js +235 -0
  71. package/lib/utilities/lambda_layers/data-masking/layer-construct.d.ts +42 -0
  72. package/lib/utilities/lambda_layers/data-masking/layer-construct.js +53 -0
  73. package/lib/utilities/lambda_layers/data-masking/layer-construct.ts +88 -0
  74. package/lib/utilities/observability/bedrock-observability.d.ts +18 -0
  75. package/lib/utilities/observability/bedrock-observability.js +131 -0
  76. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.d.ts +6 -0
  77. package/lib/utilities/observability/cloudfront-distribution-observability-property-injector.js +22 -0
  78. package/lib/utilities/observability/index.d.ts +6 -0
  79. package/lib/utilities/observability/index.js +25 -0
  80. package/lib/utilities/observability/lambda-observability-property-injector.d.ts +8 -0
  81. package/lib/utilities/observability/lambda-observability-property-injector.js +43 -0
  82. package/lib/utilities/observability/log-group-data-protection-props.d.ts +19 -0
  83. package/lib/utilities/observability/log-group-data-protection-props.js +5 -0
  84. package/lib/utilities/observability/observability.d.ts +83 -0
  85. package/lib/utilities/observability/observability.js +278 -0
  86. package/lib/utilities/observability/observable.d.ts +32 -0
  87. package/lib/utilities/observability/observable.js +3 -0
  88. package/lib/utilities/observability/powertools-config.d.ts +3 -0
  89. package/lib/utilities/observability/powertools-config.js +25 -0
  90. package/lib/utilities/observability/resources/bedrock-manage-logging-configuration/index.py +27 -0
  91. package/lib/utilities/observability/state-machine-observability-property-injector.d.ts +8 -0
  92. package/lib/utilities/observability/state-machine-observability-property-injector.js +49 -0
  93. package/lib/utilities/tests/data-loader-nag.test.d.ts +1 -0
  94. package/lib/utilities/tests/data-loader-nag.test.js +432 -0
  95. package/lib/utilities/tests/data-loader.test.d.ts +1 -0
  96. package/lib/utilities/tests/data-loader.test.js +284 -0
  97. package/lib/webapp/frontend-construct.d.ts +136 -0
  98. package/lib/webapp/frontend-construct.js +253 -0
  99. package/lib/webapp/index.d.ts +1 -0
  100. package/lib/webapp/index.js +18 -0
  101. package/lib/webapp/tests/frontend-construct-nag.test.d.ts +1 -0
  102. package/lib/webapp/tests/frontend-construct-nag.test.js +266 -0
  103. package/lib/webapp/tests/frontend-construct.test.d.ts +1 -0
  104. package/lib/webapp/tests/frontend-construct.test.js +385 -0
  105. package/package.json +183 -0
@@ -0,0 +1,509 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.BaseDocumentProcessing = exports.DocumentProcessingPrefix = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
7
+ // SPDX-License-Identifier: Apache-2.0
8
+ const path = require("node:path");
9
+ const aws_lambda_python_alpha_1 = require("@aws-cdk/aws-lambda-python-alpha");
10
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
11
+ const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
12
+ const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
13
+ const aws_iam_1 = require("aws-cdk-lib/aws-iam");
14
+ const aws_kms_1 = require("aws-cdk-lib/aws-kms");
15
+ const aws_lambda_event_sources_1 = require("aws-cdk-lib/aws-lambda-event-sources");
16
+ const aws_s3_1 = require("aws-cdk-lib/aws-s3");
17
+ const aws_s3_notifications_1 = require("aws-cdk-lib/aws-s3-notifications");
18
+ const aws_sqs_1 = require("aws-cdk-lib/aws-sqs");
19
+ const aws_stepfunctions_1 = require("aws-cdk-lib/aws-stepfunctions");
20
+ const aws_stepfunctions_tasks_1 = require("aws-cdk-lib/aws-stepfunctions-tasks");
21
+ const constructs_1 = require("constructs");
22
+ const framework_1 = require("../framework");
23
+ const utilities_1 = require("../utilities");
24
+ const lambda_observability_property_injector_1 = require("../utilities/observability/lambda-observability-property-injector");
25
+ const powertools_config_1 = require("../utilities/observability/powertools-config");
26
+ const state_machine_observability_property_injector_1 = require("../utilities/observability/state-machine-observability-property-injector");
27
+ /**
28
+ * S3 prefix constants for organizing documents throughout the processing lifecycle.
29
+ *
30
+ * Documents flow through these prefixes based on processing outcomes:
31
+ * - Upload → raw/ (triggers processing)
32
+ * - Success → processed/ (workflow completed successfully)
33
+ * - Failure → failed/ (workflow encountered errors)
34
+ */
35
+ var DocumentProcessingPrefix;
36
+ (function (DocumentProcessingPrefix) {
37
+ /** Prefix for newly uploaded documents awaiting processing */
38
+ DocumentProcessingPrefix["RAW"] = "raw/";
39
+ /** Prefix for documents that failed processing */
40
+ DocumentProcessingPrefix["FAILED"] = "failed/";
41
+ /** Prefix for successfully processed documents */
42
+ DocumentProcessingPrefix["PROCESSED"] = "processed/";
43
+ })(DocumentProcessingPrefix || (exports.DocumentProcessingPrefix = DocumentProcessingPrefix = {}));
44
+ /**
45
+ * Abstract base class for serverless document processing workflows.
46
+ *
47
+ * Provides a complete document processing pipeline with:
48
+ * - **S3 Storage**: Organized with prefixes (raw/, processed/, failed/) for document lifecycle management
49
+ * - **SQS Queue**: Reliable message processing with configurable visibility timeout and dead letter queue
50
+ * - **DynamoDB Table**: Workflow metadata tracking with DocumentId as partition key
51
+ * - **Step Functions**: Orchestrated workflow with automatic file movement based on processing outcome
52
+ * - **Auto-triggering**: S3 event notifications automatically start processing when files are uploaded to raw/ prefix
53
+ * - **Error Handling**: Failed documents are moved to failed/ prefix with error details stored in DynamoDB
54
+ * - **EventBridge Integration**: Optional custom event publishing for workflow state changes
55
+ *
56
+ * ## Architecture Flow
57
+ * S3 Upload (raw/) → SQS → Lambda Consumer → Step Functions → Processing Steps → S3 (processed/failed/)
58
+ *
59
+ * ## Implementation Requirements
60
+ * Subclasses must implement four abstract methods to define the processing workflow:
61
+ * - `classificationStep()`: Document type classification
62
+ * - `extractionStep()`: Data extraction from documents
63
+ * - `enrichmentStep()`: Optional data enrichment (return undefined to skip)
64
+ * - `postProcessingStep()`: Optional post-processing (return undefined to skip)
65
+ */
66
+ class BaseDocumentProcessing extends constructs_1.Construct {
67
+ /**
68
+ * Creates a new BaseDocumentProcessing construct.
69
+ *
70
+ * Initializes the complete document processing infrastructure including S3 bucket,
71
+ * SQS queue, DynamoDB table, and sets up S3 event notifications to trigger processing.
72
+ *
73
+ * @param scope - The scope in which to define this construct
74
+ * @param id - The scoped construct ID. Must be unique within the scope.
75
+ * @param props - Configuration properties for the document processing pipeline
76
+ */
77
+ constructor(scope, id, props) {
78
+ super(scope, id);
79
+ this.props = props;
80
+ if (props.network) {
81
+ props.network.createServiceEndpoint('vpce-sqs', aws_ec2_1.InterfaceVpcEndpointAwsService.SQS);
82
+ props.network.createServiceEndpoint('vpce-s3', aws_ec2_1.InterfaceVpcEndpointAwsService.S3);
83
+ props.network.createServiceEndpoint('vpce-sfn', aws_ec2_1.InterfaceVpcEndpointAwsService.STEP_FUNCTIONS);
84
+ props.network.createServiceEndpoint('vpce-eb', aws_ec2_1.InterfaceVpcEndpointAwsService.EVENTBRIDGE);
85
+ if (props.enableObservability) {
86
+ props.network.createServiceEndpoint('vpce-logs', aws_ec2_1.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS);
87
+ props.network.createServiceEndpoint('vpce-metrics', aws_ec2_1.InterfaceVpcEndpointAwsService.CLOUDWATCH_MONITORING);
88
+ }
89
+ }
90
+ this.encryptionKey = props.encryptionKey || new aws_kms_1.Key(this, 'IDPEncryptionKey', {
91
+ enableKeyRotation: true,
92
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
93
+ });
94
+ const bucketName = `documentprocessingbucket-${aws_cdk_lib_1.Names.uniqueResourceName(this, {
95
+ maxLength: 60 - 'documentprocessingbucket-'.length,
96
+ })}`.toLowerCase();
97
+ const bucketArn = `arn:aws:s3:::${bucketName}`;
98
+ this.encryptionKey.grantEncryptDecrypt(new aws_iam_1.ServicePrincipal('s3.amazonaws.com', {
99
+ conditions: {
100
+ ArnEquals: {
101
+ 'kms:EncryptionContext:aws:s3:arn': bucketArn,
102
+ },
103
+ },
104
+ }));
105
+ this.bucket = props.bucket || new aws_s3_1.Bucket(this, 'DocumentProcessingBucket', {
106
+ bucketName,
107
+ autoDeleteObjects: (props.removalPolicy && props.removalPolicy === aws_cdk_lib_1.RemovalPolicy.DESTROY) || !props.removalPolicy ? true : false,
108
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
109
+ encryption: aws_s3_1.BucketEncryption.KMS,
110
+ enforceSSL: true,
111
+ bucketKeyEnabled: true,
112
+ });
113
+ this.bucketEncryptionKey = this.bucket.encryptionKey;
114
+ const tempLogGroupDataProtection = props.logGroupDataProtection || {
115
+ logGroupEncryptionKey: new aws_kms_1.Key(this, 'LogGroupEncryptionKey', {
116
+ enableKeyRotation: true,
117
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
118
+ }),
119
+ };
120
+ if (!tempLogGroupDataProtection.logGroupEncryptionKey) {
121
+ this.logGroupDataProtection = {
122
+ dataProtectionIdentifiers: tempLogGroupDataProtection.dataProtectionIdentifiers,
123
+ logGroupEncryptionKey: new aws_kms_1.Key(this, 'LogGroupEncryptionKey', {
124
+ enableKeyRotation: true,
125
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
126
+ }),
127
+ };
128
+ }
129
+ else {
130
+ this.logGroupDataProtection = tempLogGroupDataProtection;
131
+ }
132
+ this.deadLetterQueue = new aws_sqs_1.Queue(this, 'DocumentProcessingDLQ', {
133
+ visibilityTimeout: props.queueVisibilityTimeout || aws_cdk_lib_1.Duration.seconds(300),
134
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
135
+ enforceSSL: true,
136
+ encryption: aws_sqs_1.QueueEncryption.KMS,
137
+ encryptionMasterKey: this.encryptionKey,
138
+ });
139
+ this.queue = new aws_sqs_1.Queue(this, 'DocumentProcessingQueue', {
140
+ visibilityTimeout: props.queueVisibilityTimeout || aws_cdk_lib_1.Duration.seconds(300),
141
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
142
+ enforceSSL: true,
143
+ deadLetterQueue: {
144
+ maxReceiveCount: props.dlqMaxReceiveCount || 5,
145
+ queue: this.deadLetterQueue,
146
+ },
147
+ encryption: aws_sqs_1.QueueEncryption.KMS,
148
+ encryptionMasterKey: this.encryptionKey,
149
+ });
150
+ this.documentProcessingTable = props.documentProcessingTable || new aws_dynamodb_1.Table(this, 'DocumentProcessingTable', {
151
+ partitionKey: {
152
+ name: 'DocumentId',
153
+ type: aws_dynamodb_1.AttributeType.STRING,
154
+ },
155
+ billingMode: aws_dynamodb_1.BillingMode.PAY_PER_REQUEST,
156
+ removalPolicy: props.removalPolicy || aws_cdk_lib_1.RemovalPolicy.DESTROY,
157
+ pointInTimeRecoverySpecification: {
158
+ pointInTimeRecoveryEnabled: true,
159
+ },
160
+ encryption: aws_dynamodb_1.TableEncryption.CUSTOMER_MANAGED,
161
+ encryptionKey: this.encryptionKey,
162
+ });
163
+ if (props.enableObservability) {
164
+ aws_cdk_lib_1.PropertyInjectors.of(this).add(new state_machine_observability_property_injector_1.StateMachineObservabilityPropertyInjector(this.logGroupDataProtection), new lambda_observability_property_injector_1.LambdaObservabilityPropertyInjector(this.logGroupDataProtection));
165
+ }
166
+ this.metricNamespace = props.metricNamespace || 'appmod-catalog';
167
+ this.metricServiceName = props.metricServiceName || 'document-processing';
168
+ }
169
+ handleStateMachineCreation(stateMachineId) {
170
+ const classificationStep = this.classificationStep();
171
+ const processingStep = this.processingStep();
172
+ const enrichmentStep = this.enrichmentStep();
173
+ const postProcessingStep = this.postProcessingStep();
174
+ const initMetadataEntry = new aws_stepfunctions_tasks_1.DynamoPutItem(this, 'InitMetadataEntry', {
175
+ table: this.documentProcessingTable,
176
+ item: {
177
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
178
+ Bucket: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.bucket')),
179
+ Key: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.key')),
180
+ WorkflowStatus: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('pending'),
181
+ StateMachineExecId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$$.Execution.Id')),
182
+ },
183
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
184
+ });
185
+ // File movement operations
186
+ const moveToFailed = this.createMoveToFailedChain();
187
+ const moveToProcessed = this.createMoveToProcessedChain();
188
+ const processingChain = processingStep
189
+ .addCatch(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ProcessingFailDDBUpdate', {
190
+ table: this.documentProcessingTable,
191
+ key: {
192
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
193
+ },
194
+ updateExpression: 'SET WorkflowStatus = :newStatus',
195
+ expressionAttributeValues: {
196
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('processing-failure'),
197
+ },
198
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
199
+ }).next(moveToFailed), {
200
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
201
+ })
202
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ProcessingSuccessUpdate', {
203
+ table: this.documentProcessingTable,
204
+ key: {
205
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
206
+ },
207
+ updateExpression: 'SET WorkflowStatus = :newStatus, ProcessingResult = :processingResult',
208
+ expressionAttributeValues: {
209
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('processing-complete'),
210
+ ':processingResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.processingResult'))),
211
+ },
212
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
213
+ }));
214
+ // Build the complete chain including optional steps
215
+ if (enrichmentStep) {
216
+ const enrichmentChain = enrichmentStep
217
+ .addCatch(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'EnrichmentFailDDBUpdate', {
218
+ table: this.documentProcessingTable,
219
+ key: {
220
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
221
+ },
222
+ updateExpression: 'SET WorkflowStatus = :newStatus',
223
+ expressionAttributeValues: {
224
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-failure'),
225
+ },
226
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
227
+ }).next(moveToFailed), {
228
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
229
+ })
230
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'EnrichmentSuccessUpdate', {
231
+ table: this.documentProcessingTable,
232
+ key: {
233
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
234
+ },
235
+ updateExpression: 'SET WorkflowStatus = :newStatus, EnrichmentResult = :enrichmentResult',
236
+ expressionAttributeValues: {
237
+ ':newStatus': postProcessingStep ? aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('enrichment-complete') : aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
238
+ ':enrichmentResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.enrichedResult'))),
239
+ },
240
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
241
+ }));
242
+ processingChain.next(enrichmentChain);
243
+ if (postProcessingStep) {
244
+ const postProcessingChain = postProcessingStep
245
+ .addCatch(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'PostProcessingFailDDBUpdate', {
246
+ table: this.documentProcessingTable,
247
+ key: {
248
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
249
+ },
250
+ updateExpression: 'SET WorkflowStatus = :newStatus',
251
+ expressionAttributeValues: {
252
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-failure'),
253
+ },
254
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
255
+ }).next(moveToFailed), {
256
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
257
+ })
258
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'PostProcessingSuccessUpdate', {
259
+ table: this.documentProcessingTable,
260
+ key: {
261
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
262
+ },
263
+ updateExpression: 'SET WorkflowStatus = :newStatus, PostProcessingResult = :postProcessingResult',
264
+ expressionAttributeValues: {
265
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
266
+ ':postProcessingResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.postProcessedResult'))),
267
+ },
268
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
269
+ }).next(moveToProcessed));
270
+ enrichmentChain.next(postProcessingChain);
271
+ }
272
+ else {
273
+ enrichmentChain.next(moveToProcessed);
274
+ }
275
+ }
276
+ else if (postProcessingStep) {
277
+ const postProcessingChain = postProcessingStep
278
+ .addCatch(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'PostProcessingFailDDBUpdate', {
279
+ table: this.documentProcessingTable,
280
+ key: {
281
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
282
+ },
283
+ updateExpression: 'SET WorkflowStatus = :newStatus',
284
+ expressionAttributeValues: {
285
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('post-processing-failure'),
286
+ },
287
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
288
+ }).next(moveToFailed), {
289
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
290
+ })
291
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'PostProcessingSuccessUpdate', {
292
+ table: this.documentProcessingTable,
293
+ key: {
294
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
295
+ },
296
+ updateExpression: 'SET WorkflowStatus = :newStatus, PostProcessingResult = :postProcessingResult',
297
+ expressionAttributeValues: {
298
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
299
+ ':postProcessingResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.postProcessedResult'))),
300
+ },
301
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
302
+ }).next(moveToProcessed));
303
+ processingChain.next(postProcessingChain);
304
+ }
305
+ else {
306
+ // No optional steps - mark as complete after extraction
307
+ processingChain.next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'WorkflowCompleteUpdate', {
308
+ table: this.documentProcessingTable,
309
+ key: {
310
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
311
+ },
312
+ updateExpression: 'SET WorkflowStatus = :newStatus',
313
+ expressionAttributeValues: {
314
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('complete'),
315
+ },
316
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
317
+ }).next(moveToProcessed));
318
+ }
319
+ const workflowDefinition = initMetadataEntry.next(classificationStep
320
+ .addCatch(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ClassificationFailDDBUpdate', {
321
+ table: this.documentProcessingTable,
322
+ key: {
323
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
324
+ },
325
+ updateExpression: 'SET WorkflowStatus = :newStatus',
326
+ expressionAttributeValues: {
327
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('classification-failure'),
328
+ },
329
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
330
+ }).next(moveToFailed), {
331
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
332
+ })
333
+ .next(new aws_stepfunctions_tasks_1.DynamoUpdateItem(this, 'ClassificationSuccessUpdate', {
334
+ table: this.documentProcessingTable,
335
+ key: {
336
+ DocumentId: aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.stringAt('$.documentId')),
337
+ },
338
+ updateExpression: 'SET WorkflowStatus = :newStatus, ClassificationResult = :classificationResult',
339
+ expressionAttributeValues: {
340
+ ':newStatus': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString('classification-complete'),
341
+ ':classificationResult': aws_stepfunctions_tasks_1.DynamoAttributeValue.fromString(aws_stepfunctions_1.JsonPath.jsonToString(aws_stepfunctions_1.JsonPath.objectAt('$.classificationResult'))),
342
+ },
343
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
344
+ }))).next(processingChain);
345
+ const role = this.createStateMachineRole();
346
+ this.encryptionKey.grantEncryptDecrypt(role);
347
+ if (this.bucketEncryptionKey) {
348
+ this.bucketEncryptionKey.grantEncryptDecrypt(role);
349
+ }
350
+ const stateMachine = new aws_stepfunctions_1.StateMachine(this, stateMachineId, {
351
+ definitionBody: aws_stepfunctions_1.DefinitionBody.fromChainable(workflowDefinition),
352
+ timeout: this.props.workflowTimeout || aws_cdk_lib_1.Duration.minutes(15),
353
+ role,
354
+ encryptionConfiguration: new aws_stepfunctions_1.CustomerManagedEncryptionConfiguration(this.encryptionKey),
355
+ });
356
+ this.handleWorkflowTrigger(stateMachine);
357
+ return stateMachine;
358
+ }
359
+ handleWorkflowTrigger(stateMachine) {
360
+ this.bucket.addEventNotification(aws_s3_1.EventType.OBJECT_CREATED, new aws_s3_notifications_1.SqsDestination(this.queue), {
361
+ prefix: DocumentProcessingPrefix.RAW,
362
+ });
363
+ this.createSQSConsumerLambda(stateMachine);
364
+ }
365
+ createSQSConsumerLambda(stateMachine) {
366
+ const { region, account } = utilities_1.LambdaIamUtils.getStackInfo(this);
367
+ // Create logs permissions and get unique function name
368
+ const logsPermissions = utilities_1.LambdaIamUtils.createLogsPermissions({
369
+ scope: this,
370
+ functionName: 'SQSConsumer',
371
+ region,
372
+ account,
373
+ });
374
+ // Create policy statements for SQS consumer Lambda
375
+ const policyStatements = [
376
+ ...logsPermissions.policyStatements,
377
+ new aws_iam_1.PolicyStatement({
378
+ effect: aws_iam_1.Effect.ALLOW,
379
+ actions: ['states:StartExecution'],
380
+ resources: [stateMachine.stateMachineArn],
381
+ }),
382
+ ];
383
+ if (this.props.network) {
384
+ policyStatements.push(utilities_1.LambdaIamUtils.generateLambdaVPCPermissions());
385
+ }
386
+ // Create IAM role for SQS consumer Lambda
387
+ const sqsConsumerRole = new aws_iam_1.Role(this, 'SQSConsumerRole', {
388
+ assumedBy: new aws_iam_1.ServicePrincipal('lambda.amazonaws.com'),
389
+ inlinePolicies: {
390
+ SQSConsumerExecutionPolicy: new aws_iam_1.PolicyDocument({
391
+ statements: policyStatements,
392
+ }),
393
+ },
394
+ });
395
+ this.encryptionKey.grantEncryptDecrypt(sqsConsumerRole);
396
+ // Create SQS consumer Lambda function
397
+ const sqsConsumerLambda = new aws_lambda_python_alpha_1.PythonFunction(this, 'SQSConsumer', {
398
+ functionName: logsPermissions.uniqueFunctionName,
399
+ runtime: framework_1.DefaultRuntimes.PYTHON,
400
+ role: sqsConsumerRole,
401
+ entry: path.join(__dirname, '/resources/default-sqs-consumer'),
402
+ environment: {
403
+ STATE_MACHINE_ARN: stateMachine.stateMachineArn,
404
+ ...powertools_config_1.PowertoolsConfig.generateDefaultLambdaConfig(this.props.enableObservability, this.metricNamespace, this.metricServiceName),
405
+ },
406
+ timeout: aws_cdk_lib_1.Duration.minutes(5),
407
+ description: 'Consumes SQS messages and triggers Step Functions executions for document processing',
408
+ environmentEncryption: this.encryptionKey,
409
+ vpc: this.props.network ? this.props.network.vpc : undefined,
410
+ vpcSubnets: this.props.network ? this.props.network.applicationSubnetSelection() : undefined,
411
+ });
412
+ // Add SQS event source to Lambda
413
+ sqsConsumerLambda.addEventSource(new aws_lambda_event_sources_1.SqsEventSource(this.queue, {
414
+ batchSize: 10,
415
+ maxBatchingWindow: aws_cdk_lib_1.Duration.seconds(5),
416
+ reportBatchItemFailures: true,
417
+ }));
418
+ return sqsConsumerLambda;
419
+ }
420
+ createStateMachineRole() {
421
+ return new aws_iam_1.Role(this, 'StateMachineRole', {
422
+ assumedBy: new aws_iam_1.ServicePrincipal('states.amazonaws.com'),
423
+ inlinePolicies: {
424
+ StateMachineExecutionPolicy: new aws_iam_1.PolicyDocument({
425
+ statements: [
426
+ new aws_iam_1.PolicyStatement({
427
+ effect: aws_iam_1.Effect.ALLOW,
428
+ actions: ['s3:GetObject', 's3:CopyObject', 's3:DeleteObject', 's3:PutObject'],
429
+ resources: [`${this.bucket.bucketArn}/*`],
430
+ }),
431
+ new aws_iam_1.PolicyStatement({
432
+ effect: aws_iam_1.Effect.ALLOW,
433
+ actions: ['dynamodb:PutItem', 'dynamodb:UpdateItem'],
434
+ resources: [this.documentProcessingTable.tableArn],
435
+ }),
436
+ ],
437
+ }),
438
+ },
439
+ });
440
+ }
441
+ createMoveToFailedChain() {
442
+ const failedChain = new aws_stepfunctions_tasks_1.CallAwsService(this, 'CopyToFailed', {
443
+ service: 's3',
444
+ action: 'copyObject',
445
+ parameters: {
446
+ Bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
447
+ CopySource: aws_stepfunctions_1.JsonPath.format('{}/{}', aws_stepfunctions_1.JsonPath.stringAt('$.bucket'), aws_stepfunctions_1.JsonPath.stringAt('$.key')),
448
+ Key: aws_stepfunctions_1.JsonPath.format('failed/{}', aws_stepfunctions_1.JsonPath.stringAt('$.filename')),
449
+ },
450
+ iamResources: [`${this.bucket.bucketArn}/*`],
451
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
452
+ }).next(new aws_stepfunctions_tasks_1.CallAwsService(this, 'DeleteFromRaw', {
453
+ service: 's3',
454
+ action: 'deleteObject',
455
+ parameters: {
456
+ Bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
457
+ Key: aws_stepfunctions_1.JsonPath.stringAt('$.key'),
458
+ },
459
+ iamResources: [`${this.bucket.bucketArn}/*`],
460
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
461
+ }));
462
+ if (this.props.eventbridgeBroker) {
463
+ failedChain.next(this.props.eventbridgeBroker.sendViaSfnChain('document-processing-failed', {
464
+ documentId: aws_stepfunctions_1.JsonPath.stringAt('$.documentId'),
465
+ bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
466
+ filename: aws_stepfunctions_1.JsonPath.stringAt('$.filename'),
467
+ }));
468
+ }
469
+ return failedChain;
470
+ }
471
+ createMoveToProcessedChain() {
472
+ const processedChain = new aws_stepfunctions_tasks_1.CallAwsService(this, 'CopyToProcessed', {
473
+ service: 's3',
474
+ action: 'copyObject',
475
+ parameters: {
476
+ Bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
477
+ CopySource: aws_stepfunctions_1.JsonPath.format('{}/{}', aws_stepfunctions_1.JsonPath.stringAt('$.bucket'), aws_stepfunctions_1.JsonPath.stringAt('$.key')),
478
+ Key: aws_stepfunctions_1.JsonPath.format('processed/{}', aws_stepfunctions_1.JsonPath.stringAt('$.filename')),
479
+ },
480
+ iamResources: [`${this.bucket.bucketArn}/*`],
481
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
482
+ }).next(new aws_stepfunctions_tasks_1.CallAwsService(this, 'DeleteFromRawSuccess', {
483
+ service: 's3',
484
+ action: 'deleteObject',
485
+ parameters: {
486
+ Bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
487
+ Key: aws_stepfunctions_1.JsonPath.stringAt('$.key'),
488
+ },
489
+ iamResources: [`${this.bucket.bucketArn}/*`],
490
+ resultPath: aws_stepfunctions_1.JsonPath.DISCARD,
491
+ }));
492
+ if (this.props.eventbridgeBroker) {
493
+ processedChain.next(this.props.eventbridgeBroker.sendViaSfnChain('document-processed-successful', {
494
+ documentId: aws_stepfunctions_1.JsonPath.stringAt('$.documentId'),
495
+ bucket: aws_stepfunctions_1.JsonPath.stringAt('$.bucket'),
496
+ filename: aws_stepfunctions_1.JsonPath.stringAt('$.filename'),
497
+ classification: aws_stepfunctions_1.JsonPath.stringAt('$.classificationResult.documentClassification'),
498
+ }));
499
+ }
500
+ return processedChain;
501
+ }
502
+ metrics() {
503
+ return [];
504
+ }
505
+ }
506
+ exports.BaseDocumentProcessing = BaseDocumentProcessing;
507
+ _a = JSII_RTTI_SYMBOL_1;
508
+ BaseDocumentProcessing[_a] = { fqn: "@cdklabs/cdk-appmod-catalog-blueprints.BaseDocumentProcessing", version: "1.0.0" };
509
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1kb2N1bWVudC1wcm9jZXNzaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdXNlLWNhc2VzL2RvY3VtZW50LXByb2Nlc3NpbmcvYmFzZS1kb2N1bWVudC1wcm9jZXNzaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEscUVBQXFFO0FBQ3JFLHNDQUFzQztBQUV0QyxrQ0FBa0M7QUFDbEMsOEVBQWtFO0FBQ2xFLDZDQUFnRjtBQUVoRiwyREFBOEY7QUFDOUYsaURBQXFFO0FBQ3JFLGlEQUFzRztBQUN0RyxpREFBZ0Q7QUFFaEQsbUZBQXNFO0FBQ3RFLCtDQUF5RTtBQUN6RSwyRUFBa0U7QUFDbEUsaURBQTZEO0FBQzdELHFFQUErSDtBQUMvSCxpRkFBMkw7QUFDM0wsMkNBQXVDO0FBQ3ZDLDRDQUF3RDtBQUV4RCw0Q0FBMkU7QUFDM0UsOEhBQXdIO0FBRXhILG9GQUFnRjtBQUNoRiw0SUFBcUk7QUFpRXJJOzs7Ozs7O0dBT0c7QUFDSCxJQUFZLHdCQU9YO0FBUEQsV0FBWSx3QkFBd0I7SUFDbEMsOERBQThEO0lBQzlELHdDQUFZLENBQUE7SUFDWixrREFBa0Q7SUFDbEQsOENBQWtCLENBQUE7SUFDbEIsa0RBQWtEO0lBQ2xELG9EQUF3QixDQUFBO0FBQzFCLENBQUMsRUFQVyx3QkFBd0Isd0NBQXhCLHdCQUF3QixRQU9uQztBQVFEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFDSCxNQUFzQixzQkFBdUIsU0FBUSxzQkFBUztJQXNCNUQ7Ozs7Ozs7OztPQVNHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFrQztRQUMxRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ2pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsVUFBVSxFQUFFLHdDQUE4QixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BGLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsU0FBUyxFQUFFLHdDQUE4QixDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2xGLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsVUFBVSxFQUFFLHdDQUE4QixDQUFDLGNBQWMsQ0FBQyxDQUFDO1lBQy9GLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsU0FBUyxFQUFFLHdDQUE4QixDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQzNGLElBQUksS0FBSyxDQUFDLG1CQUFtQixFQUFFLENBQUM7Z0JBQzlCLEtBQUssQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsV0FBVyxFQUFFLHdDQUE4QixDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUNqRyxLQUFLLENBQUMsT0FBTyxDQUFDLHFCQUFxQixDQUFDLGNBQWMsRUFBRSx3Q0FBOEIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1lBQzVHLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxDQUFDLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxJQUFJLElBQUksYUFBRyxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUM1RSxpQkFBaUIsRUFBRSxJQUFJO1lBQ3ZCLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTztTQUM1RCxDQUFDLENBQUM7UUFFSCxNQUFNLFVBQVUsR0FBRyw0QkFBNEIsbUJBQUssQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUU7WUFDNUUsU0FBUyxFQUFFLEVBQUUsR0FBRywyQkFBMkIsQ0FBQyxNQUFNO1NBQ25ELENBQUMsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBRW5CLE1BQU0sU0FBUyxHQUFHLGdCQUFnQixVQUFVLEVBQUUsQ0FBQztRQUUvQyxJQUFJLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLElBQUksMEJBQWdCLENBQUMsa0JBQWtCLEVBQUU7WUFDOUUsVUFBVSxFQUFFO2dCQUNWLFNBQVMsRUFBRTtvQkFDVCxrQ0FBa0MsRUFBRSxTQUFTO2lCQUM5QzthQUNGO1NBQ0YsQ0FBQyxDQUFDLENBQUM7UUFFSixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLElBQUksSUFBSSxlQUFNLENBQUMsSUFBSSxFQUFFLDBCQUEwQixFQUFFO1lBQ3pFLFVBQVU7WUFDVixpQkFBaUIsRUFBRSxDQUFDLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDLGFBQWEsS0FBSywyQkFBYSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLO1lBQ2hJLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTztZQUMzRCxVQUFVLEVBQUUseUJBQWdCLENBQUMsR0FBRztZQUNoQyxVQUFVLEVBQUUsSUFBSTtZQUNoQixnQkFBZ0IsRUFBRSxJQUFJO1NBQ3ZCLENBQUMsQ0FBQztRQUdILElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQztRQUVyRCxNQUFNLDBCQUEwQixHQUFHLEtBQUssQ0FBQyxzQkFBc0IsSUFBSTtZQUNqRSxxQkFBcUIsRUFBRSxJQUFJLGFBQUcsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7Z0JBQzVELGlCQUFpQixFQUFFLElBQUk7Z0JBQ3ZCLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTzthQUM1RCxDQUFDO1NBQ0gsQ0FBQztRQUVGLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ3RELElBQUksQ0FBQyxzQkFBc0IsR0FBRztnQkFDNUIseUJBQXlCLEVBQUUsMEJBQTBCLENBQUMseUJBQXlCO2dCQUMvRSxxQkFBcUIsRUFBRSxJQUFJLGFBQUcsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7b0JBQzVELGlCQUFpQixFQUFFLElBQUk7b0JBQ3ZCLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTztpQkFDNUQsQ0FBQzthQUNILENBQUM7UUFDSixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxzQkFBc0IsR0FBRywwQkFBMEIsQ0FBQztRQUMzRCxDQUFDO1FBRUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLGVBQUssQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLEVBQUU7WUFDOUQsaUJBQWlCLEVBQUUsS0FBSyxDQUFDLHNCQUFzQixJQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztZQUN4RSxhQUFhLEVBQUUsS0FBSyxDQUFDLGFBQWEsSUFBSSwyQkFBYSxDQUFDLE9BQU87WUFDM0QsVUFBVSxFQUFFLElBQUk7WUFDaEIsVUFBVSxFQUFFLHlCQUFlLENBQUMsR0FBRztZQUMvQixtQkFBbUIsRUFBRSxJQUFJLENBQUMsYUFBYTtTQUN4QyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksZUFBSyxDQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBRTtZQUN0RCxpQkFBaUIsRUFBRSxLQUFLLENBQUMsc0JBQXNCLElBQUksc0JBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDO1lBQ3hFLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTztZQUMzRCxVQUFVLEVBQUUsSUFBSTtZQUNoQixlQUFlLEVBQUU7Z0JBQ2YsZUFBZSxFQUFFLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxDQUFDO2dCQUM5QyxLQUFLLEVBQUUsSUFBSSxDQUFDLGVBQWU7YUFDNUI7WUFDRCxVQUFVLEVBQUUseUJBQWUsQ0FBQyxHQUFHO1lBQy9CLG1CQUFtQixFQUFFLElBQUksQ0FBQyxhQUFhO1NBQ3hDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyx1QkFBdUIsR0FBRyxLQUFLLENBQUMsdUJBQXVCLElBQUksSUFBSSxvQkFBSyxDQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBRTtZQUN6RyxZQUFZLEVBQUU7Z0JBQ1osSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLElBQUksRUFBRSw0QkFBYSxDQUFDLE1BQU07YUFDM0I7WUFDRCxXQUFXLEVBQUUsMEJBQVcsQ0FBQyxlQUFlO1lBQ3hDLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYSxJQUFJLDJCQUFhLENBQUMsT0FBTztZQUMzRCxnQ0FBZ0MsRUFBRTtnQkFDaEMsMEJBQTBCLEVBQUUsSUFBSTthQUNqQztZQUNELFVBQVUsRUFBRSw4QkFBZSxDQUFDLGdCQUFnQjtZQUM1QyxhQUFhLEVBQUUsSUFBSSxDQUFDLGFBQWE7U0FDbEMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxLQUFLLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM5QiwrQkFBaUIsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUM1QixJQUFJLHlGQUF5QyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxFQUMxRSxJQUFJLDRFQUFtQyxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxDQUNyRSxDQUFDO1FBQ0osQ0FBQztRQUVELElBQUksQ0FBQyxlQUFlLEdBQUcsS0FBSyxDQUFDLGVBQWUsSUFBSSxnQkFBZ0IsQ0FBQztRQUNqRSxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixJQUFJLHFCQUFxQixDQUFDO0lBQzVFLENBQUM7SUFHUywwQkFBMEIsQ0FBQyxjQUFzQjtRQUN6RCxNQUFNLGtCQUFrQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ3JELE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUM3QyxNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDN0MsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUVyRCxNQUFNLGlCQUFpQixHQUFHLElBQUksdUNBQWEsQ0FBQyxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDckUsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7WUFDbkMsSUFBSSxFQUFFO2dCQUNKLFVBQVUsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUM7Z0JBQzlFLE1BQU0sRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ3RFLEdBQUcsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQ2hFLGNBQWMsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDO2dCQUMxRCxrQkFBa0IsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsaUJBQWlCLENBQUMsQ0FBQzthQUMxRjtZQUNELFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87U0FDN0IsQ0FBQyxDQUFDO1FBRUgsMkJBQTJCO1FBQzNCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3BELE1BQU0sZUFBZSxHQUFHLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDO1FBRTFELE1BQU0sZUFBZSxHQUFHLGNBQWM7YUFDbkMsUUFBUSxDQUFDLElBQUksMENBQWdCLENBQUMsSUFBSSxFQUFFLHlCQUF5QixFQUFFO1lBQzlELEtBQUssRUFBRSxJQUFJLENBQUMsdUJBQXVCO1lBQ25DLEdBQUcsRUFBRTtnQkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQy9FO1lBQ0QsZ0JBQWdCLEVBQUUsaUNBQWlDO1lBQ25ELHlCQUF5QixFQUFFO2dCQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLG9CQUFvQixDQUFDO2FBQ3BFO1lBQ0QsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTztTQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFO1lBQ3JCLFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87U0FDN0IsQ0FBQzthQUNELElBQUksQ0FDSCxJQUFJLDBDQUFnQixDQUFDLElBQUksRUFBRSx5QkFBeUIsRUFBRTtZQUNwRCxLQUFLLEVBQUUsSUFBSSxDQUFDLHVCQUF1QjtZQUNuQyxHQUFHLEVBQUU7Z0JBQ0gsVUFBVSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQzthQUMvRTtZQUNELGdCQUFnQixFQUFFLHVFQUF1RTtZQUN6Rix5QkFBeUIsRUFBRTtnQkFDekIsWUFBWSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyxxQkFBcUIsQ0FBQztnQkFDcEUsbUJBQW1CLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsWUFBWSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLG9CQUFvQixDQUFDLENBQUMsQ0FBQzthQUNySDtZQUNELFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87U0FDN0IsQ0FBQyxDQUNILENBQUM7UUFFSixvREFBb0Q7UUFDcEQsSUFBSSxjQUFjLEVBQUUsQ0FBQztZQUNuQixNQUFNLGVBQWUsR0FBRyxjQUFjO2lCQUNuQyxRQUFRLENBQUMsSUFBSSwwQ0FBZ0IsQ0FBQyxJQUFJLEVBQUUseUJBQXlCLEVBQUU7Z0JBQzlELEtBQUssRUFBRSxJQUFJLENBQUMsdUJBQXVCO2dCQUNuQyxHQUFHLEVBQUU7b0JBQ0gsVUFBVSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztpQkFDL0U7Z0JBQ0QsZ0JBQWdCLEVBQUUsaUNBQWlDO2dCQUNuRCx5QkFBeUIsRUFBRTtvQkFDekIsWUFBWSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyxvQkFBb0IsQ0FBQztpQkFDcEU7Z0JBQ0QsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTzthQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFO2dCQUNyQixVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO2FBQzdCLENBQUM7aUJBQ0QsSUFBSSxDQUNILElBQUksMENBQWdCLENBQUMsSUFBSSxFQUFFLHlCQUF5QixFQUFFO2dCQUNwRCxLQUFLLEVBQUUsSUFBSSxDQUFDLHVCQUF1QjtnQkFDbkMsR0FBRyxFQUFFO29CQUNILFVBQVUsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUM7aUJBQy9FO2dCQUNELGdCQUFnQixFQUFFLHVFQUF1RTtnQkFDekYseUJBQXlCLEVBQUU7b0JBQ3pCLFlBQVksRUFBRSxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsOENBQW9CLENBQUMsVUFBVSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7b0JBQ3ZJLG1CQUFtQixFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyw0QkFBUSxDQUFDLFlBQVksQ0FBQyw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7aUJBQ25IO2dCQUNELFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87YUFDN0IsQ0FBQyxDQUNILENBQUM7WUFFSixlQUFlLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1lBRXRDLElBQUksa0JBQWtCLEVBQUUsQ0FBQztnQkFDdkIsTUFBTSxtQkFBbUIsR0FBRyxrQkFBa0I7cUJBQzNDLFFBQVEsQ0FBQyxJQUFJLDBDQUFnQixDQUFDLElBQUksRUFBRSw2QkFBNkIsRUFBRTtvQkFDbEUsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7b0JBQ25DLEdBQUcsRUFBRTt3QkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO3FCQUMvRTtvQkFDRCxnQkFBZ0IsRUFBRSxpQ0FBaUM7b0JBQ25ELHlCQUF5QixFQUFFO3dCQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDO3FCQUN6RTtvQkFDRCxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO2lCQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxFQUFFO29CQUNyQixVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO2lCQUM3QixDQUFDO3FCQUNELElBQUksQ0FDSCxJQUFJLDBDQUFnQixDQUFDLElBQUksRUFBRSw2QkFBNkIsRUFBRTtvQkFDeEQsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7b0JBQ25DLEdBQUcsRUFBRTt3QkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO3FCQUMvRTtvQkFDRCxnQkFBZ0IsRUFBRSwrRUFBK0U7b0JBQ2pHLHlCQUF5QixFQUFFO3dCQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQzt3QkFDekQsdUJBQXVCLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsWUFBWSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQztxQkFDNUg7b0JBQ0QsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTztpQkFDN0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FDekIsQ0FBQztnQkFDSixlQUFlLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDNUMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGVBQWUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7WUFDeEMsQ0FBQztRQUNILENBQUM7YUFBTSxJQUFJLGtCQUFrQixFQUFFLENBQUM7WUFDOUIsTUFBTSxtQkFBbUIsR0FBRyxrQkFBa0I7aUJBQzNDLFFBQVEsQ0FBQyxJQUFJLDBDQUFnQixDQUFDLElBQUksRUFBRSw2QkFBNkIsRUFBRTtnQkFDbEUsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7Z0JBQ25DLEdBQUcsRUFBRTtvQkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2lCQUMvRTtnQkFDRCxnQkFBZ0IsRUFBRSxpQ0FBaUM7Z0JBQ25ELHlCQUF5QixFQUFFO29CQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDO2lCQUN6RTtnQkFDRCxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO2FBQzdCLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUU7Z0JBQ3JCLFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87YUFDN0IsQ0FBQztpQkFDRCxJQUFJLENBQ0gsSUFBSSwwQ0FBZ0IsQ0FBQyxJQUFJLEVBQUUsNkJBQTZCLEVBQUU7Z0JBQ3hELEtBQUssRUFBRSxJQUFJLENBQUMsdUJBQXVCO2dCQUNuQyxHQUFHLEVBQUU7b0JBQ0gsVUFBVSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQztpQkFDL0U7Z0JBQ0QsZ0JBQWdCLEVBQUUsK0VBQStFO2dCQUNqRyx5QkFBeUIsRUFBRTtvQkFDekIsWUFBWSxFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUM7b0JBQ3pELHVCQUF1QixFQUFFLDhDQUFvQixDQUFDLFVBQVUsQ0FBQyw0QkFBUSxDQUFDLFlBQVksQ0FBQyw0QkFBUSxDQUFDLFFBQVEsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7aUJBQzVIO2dCQUNELFVBQVUsRUFBRSw0QkFBUSxDQUFDLE9BQU87YUFDN0IsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FDekIsQ0FBQztZQUNKLGVBQWUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUM1QyxDQUFDO2FBQU0sQ0FBQztZQUNOLHdEQUF3RDtZQUN4RCxlQUFlLENBQUMsSUFBSSxDQUNsQixJQUFJLDBDQUFnQixDQUFDLElBQUksRUFBRSx3QkFBd0IsRUFBRTtnQkFDbkQsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7Z0JBQ25DLEdBQUcsRUFBRTtvQkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2lCQUMvRTtnQkFDRCxnQkFBZ0IsRUFBRSxpQ0FBaUM7Z0JBQ25ELHlCQUF5QixFQUFFO29CQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQztpQkFDMUQ7Z0JBQ0QsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTzthQUM3QixDQUFDLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUN6QixDQUFDO1FBQ0osQ0FBQztRQUVELE1BQU0sa0JBQWtCLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUMvQyxrQkFBa0I7YUFDZixRQUFRLENBQUMsSUFBSSwwQ0FBZ0IsQ0FBQyxJQUFJLEVBQUUsNkJBQTZCLEVBQUU7WUFDbEUsS0FBSyxFQUFFLElBQUksQ0FBQyx1QkFBdUI7WUFDbkMsR0FBRyxFQUFFO2dCQUNILFVBQVUsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLENBQUM7YUFDL0U7WUFDRCxnQkFBZ0IsRUFBRSxpQ0FBaUM7WUFDbkQseUJBQXlCLEVBQUU7Z0JBQ3pCLFlBQVksRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsd0JBQXdCLENBQUM7YUFDeEU7WUFDRCxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO1NBQzdCLENBQUMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUU7WUFDckIsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTztTQUM3QixDQUFDO2FBQ0QsSUFBSSxDQUNILElBQUksMENBQWdCLENBQUMsSUFBSSxFQUFFLDZCQUE2QixFQUFFO1lBQ3hELEtBQUssRUFBRSxJQUFJLENBQUMsdUJBQXVCO1lBQ25DLEdBQUcsRUFBRTtnQkFDSCxVQUFVLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLDRCQUFRLENBQUMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO2FBQy9FO1lBQ0QsZ0JBQWdCLEVBQUUsK0VBQStFO1lBQ2pHLHlCQUF5QixFQUFFO2dCQUN6QixZQUFZLEVBQUUsOENBQW9CLENBQUMsVUFBVSxDQUFDLHlCQUF5QixDQUFDO2dCQUN4RSx1QkFBdUIsRUFBRSw4Q0FBb0IsQ0FBQyxVQUFVLENBQUMsNEJBQVEsQ0FBQyxZQUFZLENBQUMsNEJBQVEsQ0FBQyxRQUFRLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDO2FBQzdIO1lBQ0QsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTztTQUM3QixDQUFDLENBQ0gsQ0FDSixDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUV4QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUMzQyxJQUFJLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLElBQUksSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7WUFDN0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3JELENBQUM7UUFDRCxNQUFNLFlBQVksR0FBRyxJQUFJLGdDQUFZLENBQUMsSUFBSSxFQUFFLGNBQWMsRUFBRTtZQUMxRCxjQUFjLEVBQUUsa0NBQWMsQ0FBQyxhQUFhLENBQUMsa0JBQWtCLENBQUM7WUFDaEUsT0FBTyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxJQUFJLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUMzRCxJQUFJO1lBQ0osdUJBQXVCLEVBQUUsSUFBSSwwREFBc0MsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDO1NBQ3hGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUV6QyxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBRVMscUJBQXFCLENBQUMsWUFBMEI7UUFDeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxrQkFBUyxDQUFDLGNBQWMsRUFBRSxJQUFJLHFDQUFjLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ3pGLE1BQU0sRUFBRSx3QkFBd0IsQ0FBQyxHQUFHO1NBQ3JDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRU8sdUJBQXVCLENBQUMsWUFBMEI7UUFDeEQsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRywwQkFBYyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM5RCx1REFBdUQ7UUFDdkQsTUFBTSxlQUFlLEdBQUcsMEJBQWMsQ0FBQyxxQkFBcUIsQ0FBQztZQUMzRCxLQUFLLEVBQUUsSUFBSTtZQUNYLFlBQVksRUFBRSxhQUFhO1lBQzNCLE1BQU07WUFDTixPQUFPO1NBQ1IsQ0FBQyxDQUFDO1FBRUgsbURBQW1EO1FBQ25ELE1BQU0sZ0JBQWdCLEdBQUc7WUFDdkIsR0FBRyxlQUFlLENBQUMsZ0JBQWdCO1lBQ25DLElBQUkseUJBQWUsQ0FBQztnQkFDbEIsTUFBTSxFQUFFLGdCQUFNLENBQUMsS0FBSztnQkFDcEIsT0FBTyxFQUFFLENBQUMsdUJBQXVCLENBQUM7Z0JBQ2xDLFNBQVMsRUFBRSxDQUFDLFlBQVksQ0FBQyxlQUFlLENBQUM7YUFDMUMsQ0FBQztTQUNILENBQUM7UUFFRixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdkIsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLDBCQUFjLENBQUMsNEJBQTRCLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7UUFFRCwwQ0FBMEM7UUFDMUMsTUFBTSxlQUFlLEdBQUcsSUFBSSxjQUFJLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ3hELFNBQVMsRUFBRSxJQUFJLDBCQUFnQixDQUFDLHNCQUFzQixDQUFDO1lBQ3ZELGNBQWMsRUFBRTtnQkFDZCwwQkFBMEIsRUFBRSxJQUFJLHdCQUFjLENBQUM7b0JBQzdDLFVBQVUsRUFBRSxnQkFBZ0I7aUJBQzdCLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxhQUFhLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFDLENBQUM7UUFFeEQsc0NBQXNDO1FBQ3RDLE1BQU0saUJBQWlCLEdBQUcsSUFBSSx3Q0FBYyxDQUFDLElBQUksRUFBRSxhQUFhLEVBQUU7WUFDaEUsWUFBWSxFQUFFLGVBQWUsQ0FBQyxrQkFBa0I7WUFDaEQsT0FBTyxFQUFFLDJCQUFlLENBQUMsTUFBTTtZQUMvQixJQUFJLEVBQUUsZUFBZTtZQUNyQixLQUFLLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsaUNBQWlDLENBQUM7WUFDOUQsV0FBVyxFQUFFO2dCQUNYLGlCQUFpQixFQUFFLFlBQVksQ0FBQyxlQUFlO2dCQUMvQyxHQUFHLG9DQUFnQixDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUM7YUFDOUg7WUFDRCxPQUFPLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQzVCLFdBQVcsRUFBRSxzRkFBc0Y7WUFDbkcscUJBQXFCLEVBQUUsSUFBSSxDQUFDLGFBQWE7WUFDekMsR0FBRyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFNBQVM7WUFDNUQsVUFBVSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQzdGLENBQUMsQ0FBQztRQUVILGlDQUFpQztRQUNqQyxpQkFBaUIsQ0FBQyxjQUFjLENBQzlCLElBQUkseUNBQWMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFO1lBQzdCLFNBQVMsRUFBRSxFQUFFO1lBQ2IsaUJBQWlCLEVBQUUsc0JBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3RDLHVCQUF1QixFQUFFLElBQUk7U0FDOUIsQ0FBQyxDQUNILENBQUM7UUFFRixPQUFPLGlCQUFpQixDQUFDO0lBQzNCLENBQUM7SUFFTyxzQkFBc0I7UUFDNUIsT0FBTyxJQUFJLGNBQUksQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDeEMsU0FBUyxFQUFFLElBQUksMEJBQWdCLENBQUMsc0JBQXNCLENBQUM7WUFDdkQsY0FBYyxFQUFFO2dCQUNkLDJCQUEyQixFQUFFLElBQUksd0JBQWMsQ0FBQztvQkFDOUMsVUFBVSxFQUFFO3dCQUNWLElBQUkseUJBQWUsQ0FBQzs0QkFDbEIsTUFBTSxFQUFFLGdCQUFNLENBQUMsS0FBSzs0QkFDcEIsT0FBTyxFQUFFLENBQUMsY0FBYyxFQUFFLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLENBQUM7NEJBQzdFLFNBQVMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQzt5QkFDMUMsQ0FBQzt3QkFDRixJQUFJLHlCQUFlLENBQUM7NEJBQ2xCLE1BQU0sRUFBRSxnQkFBTSxDQUFDLEtBQUs7NEJBQ3BCLE9BQU8sRUFBRSxDQUFDLGtCQUFrQixFQUFFLHFCQUFxQixDQUFDOzRCQUNwRCxTQUFTLEVBQUUsQ0FBQyxJQUFJLENBQUMsdUJBQXVCLENBQUMsUUFBUSxDQUFDO3lCQUNuRCxDQUFDO3FCQUNIO2lCQUNGLENBQUM7YUFDSDtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyx1QkFBdUI7UUFDN0IsTUFBTSxXQUFXLEdBQUcsSUFBSSx3Q0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUU7WUFDM0QsT0FBTyxFQUFFLElBQUk7WUFDYixNQUFNLEVBQUUsWUFBWTtZQUNwQixVQUFVLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLDRCQUFRLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztnQkFDckMsVUFBVSxFQUFFLDRCQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztnQkFDL0YsR0FBRyxFQUFFLDRCQUFRLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUNuRTtZQUNELFlBQVksRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQztZQUM1QyxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO1NBQzdCLENBQUMsQ0FBQyxJQUFJLENBQ0wsSUFBSSx3Q0FBYyxDQUFDLElBQUksRUFBRSxlQUFlLEVBQUU7WUFDeEMsT0FBTyxFQUFFLElBQUk7WUFDYixNQUFNLEVBQUUsY0FBYztZQUN0QixVQUFVLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLDRCQUFRLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztnQkFDckMsR0FBRyxFQUFFLDRCQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQzthQUNoQztZQUNELFlBQVksRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQztZQUM1QyxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO1NBQzdCLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDakMsV0FBVyxDQUFDLElBQUksQ0FDZCxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsQ0FDMUMsNEJBQTRCLEVBQzVCO2dCQUNFLFVBQVUsRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUM7Z0JBQzdDLE1BQU0sRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7Z0JBQ3JDLFFBQVEsRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUM7YUFDMUMsQ0FDRixDQUNGLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxXQUFXLENBQUM7SUFDckIsQ0FBQztJQUVPLDBCQUEwQjtRQUNoQyxNQUFNLGNBQWMsR0FBRyxJQUFJLHdDQUFjLENBQUMsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ2pFLE9BQU8sRUFBRSxJQUFJO1lBQ2IsTUFBTSxFQUFFLFlBQVk7WUFDcEIsVUFBVSxFQUFFO2dCQUNWLE1BQU0sRUFBRSw0QkFBUSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUM7Z0JBQ3JDLFVBQVUsRUFBRSw0QkFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQy9GLEdBQUcsRUFBRSw0QkFBUSxDQUFDLE1BQU0sQ0FBQyxjQUFjLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7YUFDdEU7WUFDRCxZQUFZLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxJQUFJLENBQUM7WUFDNUMsVUFBVSxFQUFFLDRCQUFRLENBQUMsT0FBTztTQUM3QixDQUFDLENBQUMsSUFBSSxDQUNMLElBQUksd0NBQWMsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7WUFDL0MsT0FBTyxFQUFFLElBQUk7WUFDYixNQUFNLEVBQUUsY0FBYztZQUN0QixVQUFVLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLDRCQUFRLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQztnQkFDckMsR0FBRyxFQUFFLDRCQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQzthQUNoQztZQUNELFlBQVksRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLElBQUksQ0FBQztZQUM1QyxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxPQUFPO1NBQzdCLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDakMsY0FBYyxDQUFDLElBQUksQ0FDakIsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxlQUFlLENBQzFDLCtCQUErQixFQUMvQjtnQkFDRSxVQUFVLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDO2dCQUM3QyxNQUFNLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDO2dCQUNyQyxRQUFRLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDO2dCQUN6QyxjQUFjLEVBQUUsNEJBQVEsQ0FBQyxRQUFRLENBQUMsK0NBQStDLENBQUM7YUFDbkYsQ0FDRixDQUNGLENBQUM7UUFDSixDQUFDO1FBRUQsT0FBTyxjQUFjLENBQUM7SUFDeEIsQ0FBQztJQUVNLE9BQU87UUFDWixPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7O0FBbmhCSCx3REE0akJDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBQeXRob25GdW5jdGlvbiB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEtcHl0aG9uLWFscGhhJztcbmltcG9ydCB7IER1cmF0aW9uLCBOYW1lcywgUHJvcGVydHlJbmplY3RvcnMsIFJlbW92YWxQb2xpY3kgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBJTWV0cmljIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWNsb3Vkd2F0Y2gnO1xuaW1wb3J0IHsgQXR0cmlidXRlVHlwZSwgQmlsbGluZ01vZGUsIFRhYmxlLCBUYWJsZUVuY3J5cHRpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZHluYW1vZGInO1xuaW1wb3J0IHsgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgeyBFZmZlY3QsIFBvbGljeURvY3VtZW50LCBQb2xpY3lTdGF0ZW1lbnQsIFJvbGUsIFNlcnZpY2VQcmluY2lwYWwgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCB7IElLZXksIEtleSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0IHsgRnVuY3Rpb24gfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IFNxc0V2ZW50U291cmNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ldmVudC1zb3VyY2VzJztcbmltcG9ydCB7IEJ1Y2tldCwgQnVja2V0RW5jcnlwdGlvbiwgRXZlbnRUeXBlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzJztcbmltcG9ydCB7IFNxc0Rlc3RpbmF0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXMzLW5vdGlmaWNhdGlvbnMnO1xuaW1wb3J0IHsgUXVldWUsIFF1ZXVlRW5jcnlwdGlvbiB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zcXMnO1xuaW1wb3J0IHsgQ3VzdG9tZXJNYW5hZ2VkRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb24sIERlZmluaXRpb25Cb2R5LCBKc29uUGF0aCwgU3RhdGVNYWNoaW5lIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMnO1xuaW1wb3J0IHsgQmVkcm9ja0ludm9rZU1vZGVsLCBEeW5hbW9BdHRyaWJ1dGVWYWx1ZSwgRHluYW1vUHV0SXRlbSwgRHluYW1vVXBkYXRlSXRlbSwgTGFtYmRhSW52b2tlLCBDYWxsQXdzU2VydmljZSwgU3RlcEZ1bmN0aW9uc1N0YXJ0RXhlY3V0aW9uIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLXN0ZXBmdW5jdGlvbnMtdGFza3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBEZWZhdWx0UnVudGltZXMsIE5ldHdvcmsgfSBmcm9tICcuLi9mcmFtZXdvcmsnO1xuaW1wb3J0IHsgRXZlbnRicmlkZ2VCcm9rZXIgfSBmcm9tICcuLi9mcmFtZXdvcmsvZm91bmRhdGlvbi9ldmVudGJyaWRnZS1icm9rZXInO1xuaW1wb3J0IHsgTGFtYmRhSWFtVXRpbHMsIExvZ0dyb3VwRGF0YVByb3RlY3Rpb25Qcm9wcyB9IGZyb20gJy4uL3V0aWxpdGllcyc7XG5pbXBvcnQgeyBMYW1iZGFPYnNlcnZhYmlsaXR5UHJvcGVydHlJbmplY3RvciB9IGZyb20gJy4uL3V0aWxpdGllcy9vYnNlcnZhYmlsaXR5L2xhbWJkYS1vYnNlcnZhYmlsaXR5LXByb3BlcnR5LWluamVjdG9yJztcbmltcG9ydCB7IElPYnNlcnZhYmxlLCBPYnNlcnZhYmxlUHJvcHMgfSBmcm9tICcuLi91dGlsaXRpZXMvb2JzZXJ2YWJpbGl0eS9vYnNlcnZhYmxlJztcbmltcG9ydCB7IFBvd2VydG9vbHNDb25maWcgfSBmcm9tICcuLi91dGlsaXRpZXMvb2JzZXJ2YWJpbGl0eS9wb3dlcnRvb2xzLWNvbmZpZyc7XG5pbXBvcnQgeyBTdGF0ZU1hY2hpbmVPYnNlcnZhYmlsaXR5UHJvcGVydHlJbmplY3RvciB9IGZyb20gJy4uL3V0aWxpdGllcy9vYnNlcnZhYmlsaXR5L3N0YXRlLW1hY2hpbmUtb2JzZXJ2YWJpbGl0eS1wcm9wZXJ0eS1pbmplY3Rvcic7XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHMgZXh0ZW5kcyBPYnNlcnZhYmxlUHJvcHMge1xuICAvKipcbiAgICogUzMgYnVja2V0IGZvciBkb2N1bWVudCBzdG9yYWdlIHdpdGggb3JnYW5pemVkIHByZWZpeGVzIChyYXcvLCBwcm9jZXNzZWQvLCBmYWlsZWQvKS5cbiAgICogSWYgbm90IHByb3ZpZGVkLCBhIG5ldyBidWNrZXQgd2lsbCBiZSBjcmVhdGVkIHdpdGggYXV0by1kZWxldGUgZW5hYmxlZCBiYXNlZCBvbiByZW1vdmFsUG9saWN5LlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0PzogQnVja2V0O1xuICAvKipcbiAgICogRHluYW1vREIgdGFibGUgZm9yIHN0b3JpbmcgZG9jdW1lbnQgcHJvY2Vzc2luZyBtZXRhZGF0YSBhbmQgd29ya2Zsb3cgc3RhdGUuXG4gICAqIElmIG5vdCBwcm92aWRlZCwgYSBuZXcgdGFibGUgd2lsbCBiZSBjcmVhdGVkIHdpdGggRG9jdW1lbnRJZCBhcyBwYXJ0aXRpb24ga2V5LlxuICAgKi9cbiAgcmVhZG9ubHkgZG9jdW1lbnRQcm9jZXNzaW5nVGFibGU/OiBUYWJsZTtcbiAgLyoqXG4gICAqIFNRUyBxdWV1ZSB2aXNpYmlsaXR5IHRpbWVvdXQgZm9yIHByb2Nlc3NpbmcgbWVzc2FnZXMuXG4gICAqIFNob3VsZCBiZSBsb25nZXIgdGhhbiBleHBlY3RlZCBwcm9jZXNzaW5nIHRpbWUgdG8gcHJldmVudCBkdXBsaWNhdGUgcHJvY2Vzc2luZy5cbiAgICogQGRlZmF1bHQgRHVyYXRpb24uc2Vjb25kcygzMDApXG4gICAqL1xuICByZWFkb25seSBxdWV1ZVZpc2liaWxpdHlUaW1lb3V0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgdGltZXMgYSBtZXNzYWdlIGNhbiBiZSB1bnN1Y2Nlc3NmdWxseSBkZXF1ZXVlZCBiZWZvcmUgYmVpbmcgbW92ZWQgdG8gdGhlIGRlYWQtbGV0dGVyIHF1ZXVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSBkbHFNYXhSZWNlaXZlQ291bnQ/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE1heGltdW0gZXhlY3V0aW9uIHRpbWUgZm9yIHRoZSBTdGVwIEZ1bmN0aW9ucyB3b3JrZmxvdy5cbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcygzMClcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93VGltZW91dD86IER1cmF0aW9uO1xuICAvKipcbiAgICogUmVtb3ZhbCBwb2xpY3kgZm9yIGNyZWF0ZWQgcmVzb3VyY2VzIChidWNrZXQsIHRhYmxlLCBxdWV1ZSkuXG4gICAqIEBkZWZhdWx0IFJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBFdmVudEJyaWRnZSBicm9rZXIgZm9yIHB1Ymxpc2hpbmcgY3VzdG9tIGV2ZW50cyBkdXJpbmcgcHJvY2Vzc2luZy5cbiAgICogSWYgbm90IHByb3ZpZGVkLCBubyBjdXN0b20gZXZlbnRzIHdpbGwgYmUgc2VudCBvdXQuXG4gICAqL1xuICByZWFkb25seSBldmVudGJyaWRnZUJyb2tlcj86IEV2ZW50YnJpZGdlQnJva2VyO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgbG9nZ2luZyBhbmQgdHJhY2luZyBmb3IgYWxsIHN1cHBvcnRpbmcgcmVzb3VyY2VcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZU9ic2VydmFiaWxpdHk/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZXMgdGhhdCBjYW4gcnVuIGluc2lkZSBhIFZQQyB3aWxsIGZvbGxvdyB0aGUgcHJvdmlkZWQgbmV0d29yayBjb25maWd1cmF0aW9uXG4gICAqIEBkZWZhdWx0IHJlc291cmNlcyB3aWxsIHJ1biBvdXRzaWRlIG9mIGEgVlBDXG4gICAqL1xuICByZWFkb25seSBuZXR3b3JrPzogTmV0d29yaztcblxuICAvKipcbiAgICogS01TIGtleSB0byBiZSB1c2VkLlxuICAgKiBAZGVmYXVsdCBBIG5ldyBrZXkgd291bGQgYmUgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IEtleTtcbn1cblxuLyoqXG4gKiBTMyBwcmVmaXggY29uc3RhbnRzIGZvciBvcmdhbml6aW5nIGRvY3VtZW50cyB0aHJvdWdob3V0IHRoZSBwcm9jZXNzaW5nIGxpZmVjeWNsZS5cbiAqXG4gKiBEb2N1bWVudHMgZmxvdyB0aHJvdWdoIHRoZXNlIHByZWZpeGVzIGJhc2VkIG9uIHByb2Nlc3Npbmcgb3V0Y29tZXM6XG4gKiAtIFVwbG9hZCDihpIgcmF3LyAodHJpZ2dlcnMgcHJvY2Vzc2luZylcbiAqIC0gU3VjY2VzcyDihpIgcHJvY2Vzc2VkLyAod29ya2Zsb3cgY29tcGxldGVkIHN1Y2Nlc3NmdWxseSlcbiAqIC0gRmFpbHVyZSDihpIgZmFpbGVkLyAod29ya2Zsb3cgZW5jb3VudGVyZWQgZXJyb3JzKVxuICovXG5leHBvcnQgZW51bSBEb2N1bWVudFByb2Nlc3NpbmdQcmVmaXgge1xuICAvKiogUHJlZml4IGZvciBuZXdseSB1cGxvYWRlZCBkb2N1bWVudHMgYXdhaXRpbmcgcHJvY2Vzc2luZyAqL1xuICBSQVcgPSAncmF3LycsXG4gIC8qKiBQcmVmaXggZm9yIGRvY3VtZW50cyB0aGF0IGZhaWxlZCBwcm9jZXNzaW5nICovXG4gIEZBSUxFRCA9ICdmYWlsZWQvJyxcbiAgLyoqIFByZWZpeCBmb3Igc3VjY2Vzc2Z1bGx5IHByb2Nlc3NlZCBkb2N1bWVudHMgKi9cbiAgUFJPQ0VTU0VEID0gJ3Byb2Nlc3NlZC8nLFxufVxuXG4vKipcbiAqIFVuaW9uIHR5cGUgZm9yIFN0ZXAgRnVuY3Rpb25zIHRhc2tzIHRoYXQgY2FuIGJlIHVzZWQgaW4gZG9jdW1lbnQgcHJvY2Vzc2luZyB3b3JrZmxvd3MuXG4gKiBTdXBwb3J0cyBCZWRyb2NrIG1vZGVsIGludm9jYXRpb24sIExhbWJkYSBmdW5jdGlvbiBpbnZvY2F0aW9uLCBhbmQgbmVzdGVkIFN0ZXAgRnVuY3Rpb25zIGV4ZWN1dGlvbi5cbiAqL1xuZXhwb3J0IHR5cGUgRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGUgPSBCZWRyb2NrSW52b2tlTW9kZWwgfCBMYW1iZGFJbnZva2UgfCBTdGVwRnVuY3Rpb25zU3RhcnRFeGVjdXRpb247XG5cbi8qKlxuICogQWJzdHJhY3QgYmFzZSBjbGFzcyBmb3Igc2VydmVybGVzcyBkb2N1bWVudCBwcm9jZXNzaW5nIHdvcmtmbG93cy5cbiAqXG4gKiBQcm92aWRlcyBhIGNvbXBsZXRlIGRvY3VtZW50IHByb2Nlc3NpbmcgcGlwZWxpbmUgd2l0aDpcbiAqIC0gKipTMyBTdG9yYWdlKio6IE9yZ2FuaXplZCB3aXRoIHByZWZpeGVzIChyYXcvLCBwcm9jZXNzZWQvLCBmYWlsZWQvKSBmb3IgZG9jdW1lbnQgbGlmZWN5Y2xlIG1hbmFnZW1lbnRcbiAqIC0gKipTUVMgUXVldWUqKjogUmVsaWFibGUgbWVzc2FnZSBwcm9jZXNzaW5nIHdpdGggY29uZmlndXJhYmxlIHZpc2liaWxpdHkgdGltZW91dCBhbmQgZGVhZCBsZXR0ZXIgcXVldWVcbiAqIC0gKipEeW5hbW9EQiBUYWJsZSoqOiBXb3JrZmxvdyBtZXRhZGF0YSB0cmFja2luZyB3aXRoIERvY3VtZW50SWQgYXMgcGFydGl0aW9uIGtleVxuICogLSAqKlN0ZXAgRnVuY3Rpb25zKio6IE9yY2hlc3RyYXRlZCB3b3JrZmxvdyB3aXRoIGF1dG9tYXRpYyBmaWxlIG1vdmVtZW50IGJhc2VkIG9uIHByb2Nlc3Npbmcgb3V0Y29tZVxuICogLSAqKkF1dG8tdHJpZ2dlcmluZyoqOiBTMyBldmVudCBub3RpZmljYXRpb25zIGF1dG9tYXRpY2FsbHkgc3RhcnQgcHJvY2Vzc2luZyB3aGVuIGZpbGVzIGFyZSB1cGxvYWRlZCB0byByYXcvIHByZWZpeFxuICogLSAqKkVycm9yIEhhbmRsaW5nKio6IEZhaWxlZCBkb2N1bWVudHMgYXJlIG1vdmVkIHRvIGZhaWxlZC8gcHJlZml4IHdpdGggZXJyb3IgZGV0YWlscyBzdG9yZWQgaW4gRHluYW1vREJcbiAqIC0gKipFdmVudEJyaWRnZSBJbnRlZ3JhdGlvbioqOiBPcHRpb25hbCBjdXN0b20gZXZlbnQgcHVibGlzaGluZyBmb3Igd29ya2Zsb3cgc3RhdGUgY2hhbmdlc1xuICpcbiAqICMjIEFyY2hpdGVjdHVyZSBGbG93XG4gKiBTMyBVcGxvYWQgKHJhdy8pIOKGkiBTUVMg4oaSIExhbWJkYSBDb25zdW1lciDihpIgU3RlcCBGdW5jdGlvbnMg4oaSIFByb2Nlc3NpbmcgU3RlcHMg4oaSIFMzIChwcm9jZXNzZWQvZmFpbGVkLylcbiAqXG4gKiAjIyBJbXBsZW1lbnRhdGlvbiBSZXF1aXJlbWVudHNcbiAqIFN1YmNsYXNzZXMgbXVzdCBpbXBsZW1lbnQgZm91ciBhYnN0cmFjdCBtZXRob2RzIHRvIGRlZmluZSB0aGUgcHJvY2Vzc2luZyB3b3JrZmxvdzpcbiAqIC0gYGNsYXNzaWZpY2F0aW9uU3RlcCgpYDogRG9jdW1lbnQgdHlwZSBjbGFzc2lmaWNhdGlvblxuICogLSBgZXh0cmFjdGlvblN0ZXAoKWA6IERhdGEgZXh0cmFjdGlvbiBmcm9tIGRvY3VtZW50c1xuICogLSBgZW5yaWNobWVudFN0ZXAoKWA6IE9wdGlvbmFsIGRhdGEgZW5yaWNobWVudCAocmV0dXJuIHVuZGVmaW5lZCB0byBza2lwKVxuICogLSBgcG9zdFByb2Nlc3NpbmdTdGVwKClgOiBPcHRpb25hbCBwb3N0LXByb2Nlc3NpbmcgKHJldHVybiB1bmRlZmluZWQgdG8gc2tpcClcbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEJhc2VEb2N1bWVudFByb2Nlc3NpbmcgZXh0ZW5kcyBDb25zdHJ1Y3QgaW1wbGVtZW50cyBJT2JzZXJ2YWJsZSB7XG4gIC8qKiBCdXNpbmVzcyBtZXRyaWMgc2VydmljZSBuYW1lLiBUaGlzIGlzIHBhcnQgb2YgdGhlIGluaXRpYWwgc2VydmljZSBkaW1lbnNpb24gKi9cbiAgcmVhZG9ubHkgbWV0cmljU2VydmljZU5hbWU6IHN0cmluZztcbiAgLyoqIEJ1c2luZXNzIG1ldHJpYyBuYW1lc3BhY2UuICovXG4gIHJlYWRvbmx5IG1ldHJpY05hbWVzcGFjZTogc3RyaW5nO1xuICAvKiogbG9nIGdyb3VwIGRhdGEgcHJvdGVjdGlvbiBjb25maWd1cmF0aW9uICovXG4gIHJlYWRvbmx5IGxvZ0dyb3VwRGF0YVByb3RlY3Rpb246IExvZ0dyb3VwRGF0YVByb3RlY3Rpb25Qcm9wcztcbiAgLyoqIFMzIGJ1Y2tldCBmb3IgZG9jdW1lbnQgc3RvcmFnZSB3aXRoIG9yZ2FuaXplZCBwcmVmaXhlcyAocmF3LywgcHJvY2Vzc2VkLywgZmFpbGVkLykgKi9cbiAgcmVhZG9ubHkgYnVja2V0OiBCdWNrZXQ7XG4gIC8qKiBTUVMgcXVldWUgZm9yIHJlbGlhYmxlIG1lc3NhZ2UgcHJvY2Vzc2luZyB3aXRoIGRlYWQgbGV0dGVyIHF1ZXVlIHN1cHBvcnQgKi9cbiAgcmVhZG9ubHkgcXVldWU6IFF1ZXVlO1xuICAvKiogRHluYW1vREIgdGFibGUgZm9yIHN0b3JpbmcgZG9jdW1lbnQgcHJvY2Vzc2luZyBtZXRhZGF0YSBhbmQgd29ya2Zsb3cgc3RhdGUgKi9cbiAgcmVhZG9ubHkgZG9jdW1lbnRQcm9jZXNzaW5nVGFibGU6IFRhYmxlO1xuICAvKiogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciB0aGUgZG9jdW1lbnQgcHJvY2Vzc2luZyBwaXBlbGluZSAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBCYXNlRG9jdW1lbnRQcm9jZXNzaW5nUHJvcHM7XG4gIC8qKiBEZWFkIGxldHRlciBxdWV1ZSAgKi9cbiAgcmVhZG9ubHkgZGVhZExldHRlclF1ZXVlOiBRdWV1ZTtcbiAgLyoqIEtNUyBrZXkgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleTogS2V5O1xuICAvKiogRW5jcnlwdGlvbiBrZXkgdXNlZCBieSB0aGUgRG9jdW1lbnRQcm9jZXNzaW5nQnVja2V0ICovXG4gIHJlYWRvbmx5IGJ1Y2tldEVuY3J5cHRpb25LZXk/OiBJS2V5O1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IEJhc2VEb2N1bWVudFByb2Nlc3NpbmcgY29uc3RydWN0LlxuICAgKlxuICAgKiBJbml0aWFsaXplcyB0aGUgY29tcGxldGUgZG9jdW1lbnQgcHJvY2Vzc2luZyBpbmZyYXN0cnVjdHVyZSBpbmNsdWRpbmcgUzMgYnVja2V0LFxuICAgKiBTUVMgcXVldWUsIER5bmFtb0RCIHRhYmxlLCBhbmQgc2V0cyB1cCBTMyBldmVudCBub3RpZmljYXRpb25zIHRvIHRyaWdnZXIgcHJvY2Vzc2luZy5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIC0gVGhlIHNjb3BlIGluIHdoaWNoIHRvIGRlZmluZSB0aGlzIGNvbnN0cnVjdFxuICAgKiBAcGFyYW0gaWQgLSBUaGUgc2NvcGVkIGNvbnN0cnVjdCBJRC4gTXVzdCBiZSB1bmlxdWUgd2l0aGluIHRoZSBzY29wZS5cbiAgICogQHBhcmFtIHByb3BzIC0gQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIGZvciB0aGUgZG9jdW1lbnQgcHJvY2Vzc2luZyBwaXBlbGluZVxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEJhc2VEb2N1bWVudFByb2Nlc3NpbmdQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuICAgIGlmIChwcm9wcy5uZXR3b3JrKSB7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1zcXMnLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuU1FTKTtcbiAgICAgIHByb3BzLm5ldHdvcmsuY3JlYXRlU2VydmljZUVuZHBvaW50KCd2cGNlLXMzJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLlMzKTtcbiAgICAgIHByb3BzLm5ldHdvcmsuY3JlYXRlU2VydmljZUVuZHBvaW50KCd2cGNlLXNmbicsIEludGVyZmFjZVZwY0VuZHBvaW50QXdzU2VydmljZS5TVEVQX0ZVTkNUSU9OUyk7XG4gICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1lYicsIEludGVyZmFjZVZwY0VuZHBvaW50QXdzU2VydmljZS5FVkVOVEJSSURHRSk7XG4gICAgICBpZiAocHJvcHMuZW5hYmxlT2JzZXJ2YWJpbGl0eSkge1xuICAgICAgICBwcm9wcy5uZXR3b3JrLmNyZWF0ZVNlcnZpY2VFbmRwb2ludCgndnBjZS1sb2dzJywgSW50ZXJmYWNlVnBjRW5kcG9pbnRBd3NTZXJ2aWNlLkNMT1VEV0FUQ0hfTE9HUyk7XG4gICAgICAgIHByb3BzLm5ldHdvcmsuY3JlYXRlU2VydmljZUVuZHBvaW50KCd2cGNlLW1ldHJpY3MnLCBJbnRlcmZhY2VWcGNFbmRwb2ludEF3c1NlcnZpY2UuQ0xPVURXQVRDSF9NT05JVE9SSU5HKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmVuY3J5cHRpb25LZXkgPSBwcm9wcy5lbmNyeXB0aW9uS2V5IHx8IG5ldyBLZXkodGhpcywgJ0lEUEVuY3J5cHRpb25LZXknLCB7XG4gICAgICBlbmFibGVLZXlSb3RhdGlvbjogdHJ1ZSxcbiAgICAgIHJlbW92YWxQb2xpY3k6IHByb3BzLnJlbW92YWxQb2xpY3kgfHwgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYnVja2V0TmFtZSA9IGBkb2N1bWVudHByb2Nlc3NpbmdidWNrZXQtJHtOYW1lcy51bmlxdWVSZXNvdXJjZU5hbWUodGhpcywge1xuICAgICAgbWF4TGVuZ3RoOiA2MCAtICdkb2N1bWVudHByb2Nlc3NpbmdidWNrZXQtJy5sZW5ndGgsXG4gICAgfSl9YC50b0xvd2VyQ2FzZSgpO1xuXG4gICAgY29uc3QgYnVja2V0QXJuID0gYGFybjphd3M6czM6Ojoke2J1Y2tldE5hbWV9YDtcblxuICAgIHRoaXMuZW5jcnlwdGlvbktleS5ncmFudEVuY3J5cHREZWNyeXB0KG5ldyBTZXJ2aWNlUHJpbmNpcGFsKCdzMy5hbWF6b25hd3MuY29tJywge1xuICAgICAgY29uZGl0aW9uczoge1xuICAgICAgICBBcm5FcXVhbHM6IHtcbiAgICAgICAgICAna21zOkVuY3J5cHRpb25Db250ZXh0OmF3czpzMzphcm4nOiBidWNrZXRBcm4sXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH0pKTtcblxuICAgIHRoaXMuYnVja2V0ID0gcHJvcHMuYnVja2V0IHx8IG5ldyBCdWNrZXQodGhpcywgJ0RvY3VtZW50UHJvY2Vzc2luZ0J1Y2tldCcsIHtcbiAgICAgIGJ1Y2tldE5hbWUsXG4gICAgICBhdXRvRGVsZXRlT2JqZWN0czogKHByb3BzLnJlbW92YWxQb2xpY3kgJiYgcHJvcHMucmVtb3ZhbFBvbGljeSA9PT0gUmVtb3ZhbFBvbGljeS5ERVNUUk9ZKSB8fCAhcHJvcHMucmVtb3ZhbFBvbGljeSA/IHRydWUgOiBmYWxzZSxcbiAgICAgIHJlbW92YWxQb2xpY3k6IHByb3BzLnJlbW92YWxQb2xpY3kgfHwgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgZW5jcnlwdGlvbjogQnVja2V0RW5jcnlwdGlvbi5LTVMsXG4gICAgICBlbmZvcmNlU1NMOiB0cnVlLFxuICAgICAgYnVja2V0S2V5RW5hYmxlZDogdHJ1ZSxcbiAgICB9KTtcblxuXG4gICAgdGhpcy5idWNrZXRFbmNyeXB0aW9uS2V5ID0gdGhpcy5idWNrZXQuZW5jcnlwdGlvbktleTtcblxuICAgIGNvbnN0IHRlbXBMb2dHcm91cERhdGFQcm90ZWN0aW9uID0gcHJvcHMubG9nR3JvdXBEYXRhUHJvdGVjdGlvbiB8fCB7XG4gICAgICBsb2dHcm91cEVuY3J5cHRpb25LZXk6IG5ldyBLZXkodGhpcywgJ0xvZ0dyb3VwRW5jcnlwdGlvbktleScsIHtcbiAgICAgICAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gICAgICAgIHJlbW92YWxQb2xpY3k6IHByb3BzLnJlbW92YWxQb2xpY3kgfHwgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgfSksXG4gICAgfTtcblxuICAgIGlmICghdGVtcExvZ0dyb3VwRGF0YVByb3RlY3Rpb24ubG9nR3JvdXBFbmNyeXB0aW9uS2V5KSB7XG4gICAgICB0aGlzLmxvZ0dyb3VwRGF0YVByb3RlY3Rpb24gPSB7XG4gICAgICAgIGRhdGFQcm90ZWN0aW9uSWRlbnRpZmllcnM6IHRlbXBMb2dHcm91cERhdGFQcm90ZWN0aW9uLmRhdGFQcm90ZWN0aW9uSWRlbnRpZmllcnMsXG4gICAgICAgIGxvZ0dyb3VwRW5jcnlwdGlvbktleTogbmV3IEtleSh0aGlzLCAnTG9nR3JvdXBFbmNyeXB0aW9uS2V5Jywge1xuICAgICAgICAgIGVuYWJsZUtleVJvdGF0aW9uOiB0cnVlLFxuICAgICAgICAgIHJlbW92YWxQb2xpY3k6IHByb3BzLnJlbW92YWxQb2xpY3kgfHwgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLFxuICAgICAgICB9KSxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9nR3JvdXBEYXRhUHJvdGVjdGlvbiA9IHRlbXBMb2dHcm91cERhdGFQcm90ZWN0aW9uO1xuICAgIH1cblxuICAgIHRoaXMuZGVhZExldHRlclF1ZXVlID0gbmV3IFF1ZXVlKHRoaXMsICdEb2N1bWVudFByb2Nlc3NpbmdETFEnLCB7XG4gICAgICB2aXNpYmlsaXR5VGltZW91dDogcHJvcHMucXVldWVWaXNpYmlsaXR5VGltZW91dCB8fCBEdXJhdGlvbi5zZWNvbmRzKDMwMCksXG4gICAgICByZW1vdmFsUG9saWN5OiBwcm9wcy5yZW1vdmFsUG9saWN5IHx8IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICBlbmNyeXB0aW9uOiBRdWV1ZUVuY3J5cHRpb24uS01TLFxuICAgICAgZW5jcnlwdGlvbk1hc3RlcktleTogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgIH0pO1xuXG4gICAgdGhpcy5xdWV1ZSA9IG5ldyBRdWV1ZSh0aGlzLCAnRG9jdW1lbnRQcm9jZXNzaW5nUXVldWUnLCB7XG4gICAgICB2aXNpYmlsaXR5VGltZW91dDogcHJvcHMucXVldWVWaXNpYmlsaXR5VGltZW91dCB8fCBEdXJhdGlvbi5zZWNvbmRzKDMwMCksXG4gICAgICByZW1vdmFsUG9saWN5OiBwcm9wcy5yZW1vdmFsUG9saWN5IHx8IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIGVuZm9yY2VTU0w6IHRydWUsXG4gICAgICBkZWFkTGV0dGVyUXVldWU6IHtcbiAgICAgICAgbWF4UmVjZWl2ZUNvdW50OiBwcm9wcy5kbHFNYXhSZWNlaXZlQ291bnQgfHwgNSxcbiAgICAgICAgcXVldWU6IHRoaXMuZGVhZExldHRlclF1ZXVlLFxuICAgICAgfSxcbiAgICAgIGVuY3J5cHRpb246IFF1ZXVlRW5jcnlwdGlvbi5LTVMsXG4gICAgICBlbmNyeXB0aW9uTWFzdGVyS2V5OiB0aGlzLmVuY3J5cHRpb25LZXksXG4gICAgfSk7XG5cbiAgICB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlID0gcHJvcHMuZG9jdW1lbnRQcm9jZXNzaW5nVGFibGUgfHwgbmV3IFRhYmxlKHRoaXMsICdEb2N1bWVudFByb2Nlc3NpbmdUYWJsZScsIHtcbiAgICAgIHBhcnRpdGlvbktleToge1xuICAgICAgICBuYW1lOiAnRG9jdW1lbnRJZCcsXG4gICAgICAgIHR5cGU6IEF0dHJpYnV0ZVR5cGUuU1RSSU5HLFxuICAgICAgfSxcbiAgICAgIGJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QsXG4gICAgICByZW1vdmFsUG9saWN5OiBwcm9wcy5yZW1vdmFsUG9saWN5IHx8IFJlbW92YWxQb2xpY3kuREVTVFJPWSxcbiAgICAgIHBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uOiB7XG4gICAgICAgIHBvaW50SW5UaW1lUmVjb3ZlcnlFbmFibGVkOiB0cnVlLFxuICAgICAgfSxcbiAgICAgIGVuY3J5cHRpb246IFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VELFxuICAgICAgZW5jcnlwdGlvbktleTogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmVuYWJsZU9ic2VydmFiaWxpdHkpIHtcbiAgICAgIFByb3BlcnR5SW5qZWN0b3JzLm9mKHRoaXMpLmFkZChcbiAgICAgICAgbmV3IFN0YXRlTWFjaGluZU9ic2VydmFiaWxpdHlQcm9wZXJ0eUluamVjdG9yKHRoaXMubG9nR3JvdXBEYXRhUHJvdGVjdGlvbiksXG4gICAgICAgIG5ldyBMYW1iZGFPYnNlcnZhYmlsaXR5UHJvcGVydHlJbmplY3Rvcih0aGlzLmxvZ0dyb3VwRGF0YVByb3RlY3Rpb24pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLm1ldHJpY05hbWVzcGFjZSA9IHByb3BzLm1ldHJpY05hbWVzcGFjZSB8fCAnYXBwbW9kLWNhdGFsb2cnO1xuICAgIHRoaXMubWV0cmljU2VydmljZU5hbWUgPSBwcm9wcy5tZXRyaWNTZXJ2aWNlTmFtZSB8fCAnZG9jdW1lbnQtcHJvY2Vzc2luZyc7XG4gIH1cblxuXG4gIHByb3RlY3RlZCBoYW5kbGVTdGF0ZU1hY2hpbmVDcmVhdGlvbihzdGF0ZU1hY2hpbmVJZDogc3RyaW5nKSB7XG4gICAgY29uc3QgY2xhc3NpZmljYXRpb25TdGVwID0gdGhpcy5jbGFzc2lmaWNhdGlvblN0ZXAoKTtcbiAgICBjb25zdCBwcm9jZXNzaW5nU3RlcCA9IHRoaXMucHJvY2Vzc2luZ1N0ZXAoKTtcbiAgICBjb25zdCBlbnJpY2htZW50U3RlcCA9IHRoaXMuZW5yaWNobWVudFN0ZXAoKTtcbiAgICBjb25zdCBwb3N0UHJvY2Vzc2luZ1N0ZXAgPSB0aGlzLnBvc3RQcm9jZXNzaW5nU3RlcCgpO1xuXG4gICAgY29uc3QgaW5pdE1ldGFkYXRhRW50cnkgPSBuZXcgRHluYW1vUHV0SXRlbSh0aGlzLCAnSW5pdE1ldGFkYXRhRW50cnknLCB7XG4gICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgIGl0ZW06IHtcbiAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICBCdWNrZXQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuYnVja2V0JykpLFxuICAgICAgICBLZXk6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQua2V5JykpLFxuICAgICAgICBXb3JrZmxvd1N0YXR1czogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygncGVuZGluZycpLFxuICAgICAgICBTdGF0ZU1hY2hpbmVFeGVjSWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQkLkV4ZWN1dGlvbi5JZCcpKSxcbiAgICAgIH0sXG4gICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgIH0pO1xuXG4gICAgLy8gRmlsZSBtb3ZlbWVudCBvcGVyYXRpb25zXG4gICAgY29uc3QgbW92ZVRvRmFpbGVkID0gdGhpcy5jcmVhdGVNb3ZlVG9GYWlsZWRDaGFpbigpO1xuICAgIGNvbnN0IG1vdmVUb1Byb2Nlc3NlZCA9IHRoaXMuY3JlYXRlTW92ZVRvUHJvY2Vzc2VkQ2hhaW4oKTtcblxuICAgIGNvbnN0IHByb2Nlc3NpbmdDaGFpbiA9IHByb2Nlc3NpbmdTdGVwXG4gICAgICAuYWRkQ2F0Y2gobmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ1Byb2Nlc3NpbmdGYWlsRERCVXBkYXRlJywge1xuICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAga2V5OiB7XG4gICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICB9LFxuICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ3Byb2Nlc3NpbmctZmFpbHVyZScpLFxuICAgICAgICB9LFxuICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgfSkubmV4dChtb3ZlVG9GYWlsZWQpLCB7XG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KVxuICAgICAgLm5leHQoXG4gICAgICAgIG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdQcm9jZXNzaW5nU3VjY2Vzc1VwZGF0ZScsIHtcbiAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICBrZXk6IHtcbiAgICAgICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVwZGF0ZUV4cHJlc3Npb246ICdTRVQgV29ya2Zsb3dTdGF0dXMgPSA6bmV3U3RhdHVzLCBQcm9jZXNzaW5nUmVzdWx0ID0gOnByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygncHJvY2Vzc2luZy1jb21wbGV0ZScpLFxuICAgICAgICAgICAgJzpwcm9jZXNzaW5nUmVzdWx0JzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5qc29uVG9TdHJpbmcoSnNvblBhdGgub2JqZWN0QXQoJyQucHJvY2Vzc2luZ1Jlc3VsdCcpKSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICB9KSxcbiAgICAgICk7XG5cbiAgICAvLyBCdWlsZCB0aGUgY29tcGxldGUgY2hhaW4gaW5jbHVkaW5nIG9wdGlvbmFsIHN0ZXBzXG4gICAgaWYgKGVucmljaG1lbnRTdGVwKSB7XG4gICAgICBjb25zdCBlbnJpY2htZW50Q2hhaW4gPSBlbnJpY2htZW50U3RlcFxuICAgICAgICAuYWRkQ2F0Y2gobmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ0VucmljaG1lbnRGYWlsRERCVXBkYXRlJywge1xuICAgICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMnLFxuICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnZW5yaWNobWVudC1mYWlsdXJlJyksXG4gICAgICAgICAgfSxcbiAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICB9KS5uZXh0KG1vdmVUb0ZhaWxlZCksIHtcbiAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICB9KVxuICAgICAgICAubmV4dChcbiAgICAgICAgICBuZXcgRHluYW1vVXBkYXRlSXRlbSh0aGlzLCAnRW5yaWNobWVudFN1Y2Nlc3NVcGRhdGUnLCB7XG4gICAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMsIEVucmljaG1lbnRSZXN1bHQgPSA6ZW5yaWNobWVudFJlc3VsdCcsXG4gICAgICAgICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAgICc6bmV3U3RhdHVzJzogcG9zdFByb2Nlc3NpbmdTdGVwID8gRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnZW5yaWNobWVudC1jb21wbGV0ZScpIDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnY29tcGxldGUnKSxcbiAgICAgICAgICAgICAgJzplbnJpY2htZW50UmVzdWx0JzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5qc29uVG9TdHJpbmcoSnNvblBhdGgub2JqZWN0QXQoJyQuZW5yaWNoZWRSZXN1bHQnKSkpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG5cbiAgICAgIHByb2Nlc3NpbmdDaGFpbi5uZXh0KGVucmljaG1lbnRDaGFpbik7XG5cbiAgICAgIGlmIChwb3N0UHJvY2Vzc2luZ1N0ZXApIHtcbiAgICAgICAgY29uc3QgcG9zdFByb2Nlc3NpbmdDaGFpbiA9IHBvc3RQcm9jZXNzaW5nU3RlcFxuICAgICAgICAgIC5hZGRDYXRjaChuZXcgRHluYW1vVXBkYXRlSXRlbSh0aGlzLCAnUG9zdFByb2Nlc3NpbmdGYWlsRERCVXBkYXRlJywge1xuICAgICAgICAgICAgdGFibGU6IHRoaXMuZG9jdW1lbnRQcm9jZXNzaW5nVGFibGUsXG4gICAgICAgICAgICBrZXk6IHtcbiAgICAgICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVwZGF0ZUV4cHJlc3Npb246ICdTRVQgV29ya2Zsb3dTdGF0dXMgPSA6bmV3U3RhdHVzJyxcbiAgICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAgICAgJzpuZXdTdGF0dXMnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdwb3N0LXByb2Nlc3NpbmctZmFpbHVyZScpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgICAgfSkubmV4dChtb3ZlVG9GYWlsZWQpLCB7XG4gICAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICAgIH0pXG4gICAgICAgICAgLm5leHQoXG4gICAgICAgICAgICBuZXcgRHluYW1vVXBkYXRlSXRlbSh0aGlzLCAnUG9zdFByb2Nlc3NpbmdTdWNjZXNzVXBkYXRlJywge1xuICAgICAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICAgICAga2V5OiB7XG4gICAgICAgICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cywgUG9zdFByb2Nlc3NpbmdSZXN1bHQgPSA6cG9zdFByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgICAgICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAgICAgJzpuZXdTdGF0dXMnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdjb21wbGV0ZScpLFxuICAgICAgICAgICAgICAgICc6cG9zdFByb2Nlc3NpbmdSZXN1bHQnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5wb3N0UHJvY2Vzc2VkUmVzdWx0JykpKSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgcmVzdWx0UGF0aDogSnNvblBhdGguRElTQ0FSRCxcbiAgICAgICAgICAgIH0pLm5leHQobW92ZVRvUHJvY2Vzc2VkKSxcbiAgICAgICAgICApO1xuICAgICAgICBlbnJpY2htZW50Q2hhaW4ubmV4dChwb3N0UHJvY2Vzc2luZ0NoYWluKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGVucmljaG1lbnRDaGFpbi5uZXh0KG1vdmVUb1Byb2Nlc3NlZCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwb3N0UHJvY2Vzc2luZ1N0ZXApIHtcbiAgICAgIGNvbnN0IHBvc3RQcm9jZXNzaW5nQ2hhaW4gPSBwb3N0UHJvY2Vzc2luZ1N0ZXBcbiAgICAgICAgLmFkZENhdGNoKG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdQb3N0UHJvY2Vzc2luZ0ZhaWxEREJVcGRhdGUnLCB7XG4gICAgICAgICAgdGFibGU6IHRoaXMuZG9jdW1lbnRQcm9jZXNzaW5nVGFibGUsXG4gICAgICAgICAga2V5OiB7XG4gICAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgICAgfSxcbiAgICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cycsXG4gICAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgJzpuZXdTdGF0dXMnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdwb3N0LXByb2Nlc3NpbmctZmFpbHVyZScpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgcmVzdWx0UGF0aDogSnNvblBhdGguRElTQ0FSRCxcbiAgICAgICAgfSkubmV4dChtb3ZlVG9GYWlsZWQpLCB7XG4gICAgICAgICAgcmVzdWx0UGF0aDogSnNvblBhdGguRElTQ0FSRCxcbiAgICAgICAgfSlcbiAgICAgICAgLm5leHQoXG4gICAgICAgICAgbmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ1Bvc3RQcm9jZXNzaW5nU3VjY2Vzc1VwZGF0ZScsIHtcbiAgICAgICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICAgICAga2V5OiB7XG4gICAgICAgICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1cGRhdGVFeHByZXNzaW9uOiAnU0VUIFdvcmtmbG93U3RhdHVzID0gOm5ld1N0YXR1cywgUG9zdFByb2Nlc3NpbmdSZXN1bHQgPSA6cG9zdFByb2Nlc3NpbmdSZXN1bHQnLFxuICAgICAgICAgICAgZXhwcmVzc2lvbkF0dHJpYnV0ZVZhbHVlczoge1xuICAgICAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ2NvbXBsZXRlJyksXG4gICAgICAgICAgICAgICc6cG9zdFByb2Nlc3NpbmdSZXN1bHQnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLmpzb25Ub1N0cmluZyhKc29uUGF0aC5vYmplY3RBdCgnJC5wb3N0UHJvY2Vzc2VkUmVzdWx0JykpKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgICAgIH0pLm5leHQobW92ZVRvUHJvY2Vzc2VkKSxcbiAgICAgICAgKTtcbiAgICAgIHByb2Nlc3NpbmdDaGFpbi5uZXh0KHBvc3RQcm9jZXNzaW5nQ2hhaW4pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBObyBvcHRpb25hbCBzdGVwcyAtIG1hcmsgYXMgY29tcGxldGUgYWZ0ZXIgZXh0cmFjdGlvblxuICAgICAgcHJvY2Vzc2luZ0NoYWluLm5leHQoXG4gICAgICAgIG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdXb3JrZmxvd0NvbXBsZXRlVXBkYXRlJywge1xuICAgICAgICAgIHRhYmxlOiB0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLFxuICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgRG9jdW1lbnRJZDogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5zdHJpbmdBdCgnJC5kb2N1bWVudElkJykpLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMnLFxuICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAgICc6bmV3U3RhdHVzJzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZygnY29tcGxldGUnKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgIH0pLm5leHQobW92ZVRvUHJvY2Vzc2VkKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3Qgd29ya2Zsb3dEZWZpbml0aW9uID0gaW5pdE1ldGFkYXRhRW50cnkubmV4dChcbiAgICAgIGNsYXNzaWZpY2F0aW9uU3RlcFxuICAgICAgICAuYWRkQ2F0Y2gobmV3IER5bmFtb1VwZGF0ZUl0ZW0odGhpcywgJ0NsYXNzaWZpY2F0aW9uRmFpbEREQlVwZGF0ZScsIHtcbiAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICBrZXk6IHtcbiAgICAgICAgICAgIERvY3VtZW50SWQ6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHVwZGF0ZUV4cHJlc3Npb246ICdTRVQgV29ya2Zsb3dTdGF0dXMgPSA6bmV3U3RhdHVzJyxcbiAgICAgICAgICBleHByZXNzaW9uQXR0cmlidXRlVmFsdWVzOiB7XG4gICAgICAgICAgICAnOm5ld1N0YXR1cyc6IER5bmFtb0F0dHJpYnV0ZVZhbHVlLmZyb21TdHJpbmcoJ2NsYXNzaWZpY2F0aW9uLWZhaWx1cmUnKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgIH0pLm5leHQobW92ZVRvRmFpbGVkKSwge1xuICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgIH0pXG4gICAgICAgIC5uZXh0KFxuICAgICAgICAgIG5ldyBEeW5hbW9VcGRhdGVJdGVtKHRoaXMsICdDbGFzc2lmaWNhdGlvblN1Y2Nlc3NVcGRhdGUnLCB7XG4gICAgICAgICAgICB0YWJsZTogdGhpcy5kb2N1bWVudFByb2Nlc3NpbmdUYWJsZSxcbiAgICAgICAgICAgIGtleToge1xuICAgICAgICAgICAgICBEb2N1bWVudElkOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdXBkYXRlRXhwcmVzc2lvbjogJ1NFVCBXb3JrZmxvd1N0YXR1cyA9IDpuZXdTdGF0dXMsIENsYXNzaWZpY2F0aW9uUmVzdWx0ID0gOmNsYXNzaWZpY2F0aW9uUmVzdWx0JyxcbiAgICAgICAgICAgIGV4cHJlc3Npb25BdHRyaWJ1dGVWYWx1ZXM6IHtcbiAgICAgICAgICAgICAgJzpuZXdTdGF0dXMnOiBEeW5hbW9BdHRyaWJ1dGVWYWx1ZS5mcm9tU3RyaW5nKCdjbGFzc2lmaWNhdGlvbi1jb21wbGV0ZScpLFxuICAgICAgICAgICAgICAnOmNsYXNzaWZpY2F0aW9uUmVzdWx0JzogRHluYW1vQXR0cmlidXRlVmFsdWUuZnJvbVN0cmluZyhKc29uUGF0aC5qc29uVG9TdHJpbmcoSnNvblBhdGgub2JqZWN0QXQoJyQuY2xhc3NpZmljYXRpb25SZXN1bHQnKSkpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICAgICAgfSksXG4gICAgICAgICksXG4gICAgKS5uZXh0KHByb2Nlc3NpbmdDaGFpbik7XG5cbiAgICBjb25zdCByb2xlID0gdGhpcy5jcmVhdGVTdGF0ZU1hY2hpbmVSb2xlKCk7XG4gICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdERlY3J5cHQocm9sZSk7XG4gICAgaWYgKHRoaXMuYnVja2V0RW5jcnlwdGlvbktleSkge1xuICAgICAgdGhpcy5idWNrZXRFbmNyeXB0aW9uS2V5LmdyYW50RW5jcnlwdERlY3J5cHQocm9sZSk7XG4gICAgfVxuICAgIGNvbnN0IHN0YXRlTWFjaGluZSA9IG5ldyBTdGF0ZU1hY2hpbmUodGhpcywgc3RhdGVNYWNoaW5lSWQsIHtcbiAgICAgIGRlZmluaXRpb25Cb2R5OiBEZWZpbml0aW9uQm9keS5mcm9tQ2hhaW5hYmxlKHdvcmtmbG93RGVmaW5pdGlvbiksXG4gICAgICB0aW1lb3V0OiB0aGlzLnByb3BzLndvcmtmbG93VGltZW91dCB8fCBEdXJhdGlvbi5taW51dGVzKDE1KSxcbiAgICAgIHJvbGUsXG4gICAgICBlbmNyeXB0aW9uQ29uZmlndXJhdGlvbjogbmV3IEN1c3RvbWVyTWFuYWdlZEVuY3J5cHRpb25Db25maWd1cmF0aW9uKHRoaXMuZW5jcnlwdGlvbktleSksXG4gICAgfSk7XG5cbiAgICB0aGlzLmhhbmRsZVdvcmtmbG93VHJpZ2dlcihzdGF0ZU1hY2hpbmUpO1xuXG4gICAgcmV0dXJuIHN0YXRlTWFjaGluZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVXb3JrZmxvd1RyaWdnZXIoc3RhdGVNYWNoaW5lOiBTdGF0ZU1hY2hpbmUpIHtcbiAgICB0aGlzLmJ1Y2tldC5hZGRFdmVudE5vdGlmaWNhdGlvbihFdmVudFR5cGUuT0JKRUNUX0NSRUFURUQsIG5ldyBTcXNEZXN0aW5hdGlvbih0aGlzLnF1ZXVlKSwge1xuICAgICAgcHJlZml4OiBEb2N1bWVudFByb2Nlc3NpbmdQcmVmaXguUkFXLFxuICAgIH0pO1xuICAgIHRoaXMuY3JlYXRlU1FTQ29uc3VtZXJMYW1iZGEoc3RhdGVNYWNoaW5lKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlU1FTQ29uc3VtZXJMYW1iZGEoc3RhdGVNYWNoaW5lOiBTdGF0ZU1hY2hpbmUpOiBGdW5jdGlvbiB7XG4gICAgY29uc3QgeyByZWdpb24sIGFjY291bnQgfSA9IExhbWJkYUlhbVV0aWxzLmdldFN0YWNrSW5mbyh0aGlzKTtcbiAgICAvLyBDcmVhdGUgbG9ncyBwZXJtaXNzaW9ucyBhbmQgZ2V0IHVuaXF1ZSBmdW5jdGlvbiBuYW1lXG4gICAgY29uc3QgbG9nc1Blcm1pc3Npb25zID0gTGFtYmRhSWFtVXRpbHMuY3JlYXRlTG9nc1Blcm1pc3Npb25zKHtcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgZnVuY3Rpb25OYW1lOiAnU1FTQ29uc3VtZXInLFxuICAgICAgcmVnaW9uLFxuICAgICAgYWNjb3VudCxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBwb2xpY3kgc3RhdGVtZW50cyBmb3IgU1FTIGNvbnN1bWVyIExhbWJkYVxuICAgIGNvbnN0IHBvbGljeVN0YXRlbWVudHMgPSBbXG4gICAgICAuLi5sb2dzUGVybWlzc2lvbnMucG9saWN5U3RhdGVtZW50cyxcbiAgICAgIG5ldyBQb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICBlZmZlY3Q6IEVmZmVjdC5BTExPVyxcbiAgICAgICAgYWN0aW9uczogWydzdGF0ZXM6U3RhcnRFeGVjdXRpb24nXSxcbiAgICAgICAgcmVzb3VyY2VzOiBbc3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybl0sXG4gICAgICB9KSxcbiAgICBdO1xuXG4gICAgaWYgKHRoaXMucHJvcHMubmV0d29yaykge1xuICAgICAgcG9saWN5U3RhdGVtZW50cy5wdXNoKExhbWJkYUlhbVV0aWxzLmdlbmVyYXRlTGFtYmRhVlBDUGVybWlzc2lvbnMoKSk7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIElBTSByb2xlIGZvciBTUVMgY29uc3VtZXIgTGFtYmRhXG4gICAgY29uc3Qgc3FzQ29uc3VtZXJSb2xlID0gbmV3IFJvbGUodGhpcywgJ1NRU0NvbnN1bWVyUm9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IFNlcnZpY2VQcmluY2lwYWwoJ2xhbWJkYS5hbWF6b25hd3MuY29tJyksXG4gICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICBTUVNDb25zdW1lckV4ZWN1dGlvblBvbGljeTogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBwb2xpY3lTdGF0ZW1lbnRzLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLmVuY3J5cHRpb25LZXkuZ3JhbnRFbmNyeXB0RGVjcnlwdChzcXNDb25zdW1lclJvbGUpO1xuXG4gICAgLy8gQ3JlYXRlIFNRUyBjb25zdW1lciBMYW1iZGEgZnVuY3Rpb25cbiAgICBjb25zdCBzcXNDb25zdW1lckxhbWJkYSA9IG5ldyBQeXRob25GdW5jdGlvbih0aGlzLCAnU1FTQ29uc3VtZXInLCB7XG4gICAgICBmdW5jdGlvbk5hbWU6IGxvZ3NQZXJtaXNzaW9ucy51bmlxdWVGdW5jdGlvbk5hbWUsXG4gICAgICBydW50aW1lOiBEZWZhdWx0UnVudGltZXMuUFlUSE9OLFxuICAgICAgcm9sZTogc3FzQ29uc3VtZXJSb2xlLFxuICAgICAgZW50cnk6IHBhdGguam9pbihfX2Rpcm5hbWUsICcvcmVzb3VyY2VzL2RlZmF1bHQtc3FzLWNvbnN1bWVyJyksXG4gICAgICBlbnZpcm9ubWVudDoge1xuICAgICAgICBTVEFURV9NQUNISU5FX0FSTjogc3RhdGVNYWNoaW5lLnN0YXRlTWFjaGluZUFybixcbiAgICAgICAgLi4uUG93ZXJ0b29sc0NvbmZpZy5nZW5lcmF0ZURlZmF1bHRMYW1iZGFDb25maWcodGhpcy5wcm9wcy5lbmFibGVPYnNlcnZhYmlsaXR5LCB0aGlzLm1ldHJpY05hbWVzcGFjZSwgdGhpcy5tZXRyaWNTZXJ2aWNlTmFtZSksXG4gICAgICB9LFxuICAgICAgdGltZW91dDogRHVyYXRpb24ubWludXRlcyg1KSxcbiAgICAgIGRlc2NyaXB0aW9uOiAnQ29uc3VtZXMgU1FTIG1lc3NhZ2VzIGFuZCB0cmlnZ2VycyBTdGVwIEZ1bmN0aW9ucyBleGVjdXRpb25zIGZvciBkb2N1bWVudCBwcm9jZXNzaW5nJyxcbiAgICAgIGVudmlyb25tZW50RW5jcnlwdGlvbjogdGhpcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgdnBjOiB0aGlzLnByb3BzLm5ldHdvcmsgPyB0aGlzLnByb3BzLm5ldHdvcmsudnBjIDogdW5kZWZpbmVkLFxuICAgICAgdnBjU3VibmV0czogdGhpcy5wcm9wcy5uZXR3b3JrID8gdGhpcy5wcm9wcy5uZXR3b3JrLmFwcGxpY2F0aW9uU3VibmV0U2VsZWN0aW9uKCkgOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgU1FTIGV2ZW50IHNvdXJjZSB0byBMYW1iZGFcbiAgICBzcXNDb25zdW1lckxhbWJkYS5hZGRFdmVudFNvdXJjZShcbiAgICAgIG5ldyBTcXNFdmVudFNvdXJjZSh0aGlzLnF1ZXVlLCB7XG4gICAgICAgIGJhdGNoU2l6ZTogMTAsXG4gICAgICAgIG1heEJhdGNoaW5nV2luZG93OiBEdXJhdGlvbi5zZWNvbmRzKDUpLFxuICAgICAgICByZXBvcnRCYXRjaEl0ZW1GYWlsdXJlczogdHJ1ZSxcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICByZXR1cm4gc3FzQ29uc3VtZXJMYW1iZGE7XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVN0YXRlTWFjaGluZVJvbGUoKTogUm9sZSB7XG4gICAgcmV0dXJuIG5ldyBSb2xlKHRoaXMsICdTdGF0ZU1hY2hpbmVSb2xlJywge1xuICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbCgnc3RhdGVzLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgIGlubGluZVBvbGljaWVzOiB7XG4gICAgICAgIFN0YXRlTWFjaGluZUV4ZWN1dGlvblBvbGljeTogbmV3IFBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBFZmZlY3QuQUxMT1csXG4gICAgICAgICAgICAgIGFjdGlvbnM6IFsnczM6R2V0T2JqZWN0JywgJ3MzOkNvcHlPYmplY3QnLCAnczM6RGVsZXRlT2JqZWN0JywgJ3MzOlB1dE9iamVjdCddLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IFtgJHt0aGlzLmJ1Y2tldC5idWNrZXRBcm59LypgXSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICAgIGVmZmVjdDogRWZmZWN0LkFMTE9XLFxuICAgICAgICAgICAgICBhY3Rpb25zOiBbJ2R5bmFtb2RiOlB1dEl0ZW0nLCAnZHluYW1vZGI6VXBkYXRlSXRlbSddLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IFt0aGlzLmRvY3VtZW50UHJvY2Vzc2luZ1RhYmxlLnRhYmxlQXJuXSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgIH0pLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlTW92ZVRvRmFpbGVkQ2hhaW4oKSB7XG4gICAgY29uc3QgZmFpbGVkQ2hhaW4gPSBuZXcgQ2FsbEF3c1NlcnZpY2UodGhpcywgJ0NvcHlUb0ZhaWxlZCcsIHtcbiAgICAgIHNlcnZpY2U6ICdzMycsXG4gICAgICBhY3Rpb246ICdjb3B5T2JqZWN0JyxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgQnVja2V0OiBKc29uUGF0aC5zdHJpbmdBdCgnJC5idWNrZXQnKSxcbiAgICAgICAgQ29weVNvdXJjZTogSnNvblBhdGguZm9ybWF0KCd7fS97fScsIEpzb25QYXRoLnN0cmluZ0F0KCckLmJ1Y2tldCcpLCBKc29uUGF0aC5zdHJpbmdBdCgnJC5rZXknKSksXG4gICAgICAgIEtleTogSnNvblBhdGguZm9ybWF0KCdmYWlsZWQve30nLCBKc29uUGF0aC5zdHJpbmdBdCgnJC5maWxlbmFtZScpKSxcbiAgICAgIH0sXG4gICAgICBpYW1SZXNvdXJjZXM6IFtgJHt0aGlzLmJ1Y2tldC5idWNrZXRBcm59LypgXSxcbiAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgfSkubmV4dChcbiAgICAgIG5ldyBDYWxsQXdzU2VydmljZSh0aGlzLCAnRGVsZXRlRnJvbVJhdycsIHtcbiAgICAgICAgc2VydmljZTogJ3MzJyxcbiAgICAgICAgYWN0aW9uOiAnZGVsZXRlT2JqZWN0JyxcbiAgICAgICAgcGFyYW1ldGVyczoge1xuICAgICAgICAgIEJ1Y2tldDogSnNvblBhdGguc3RyaW5nQXQoJyQuYnVja2V0JyksXG4gICAgICAgICAgS2V5OiBKc29uUGF0aC5zdHJpbmdBdCgnJC5rZXknKSxcbiAgICAgICAgfSxcbiAgICAgICAgaWFtUmVzb3VyY2VzOiBbYCR7dGhpcy5idWNrZXQuYnVja2V0QXJufS8qYF0sXG4gICAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKHRoaXMucHJvcHMuZXZlbnRicmlkZ2VCcm9rZXIpIHtcbiAgICAgIGZhaWxlZENoYWluLm5leHQoXG4gICAgICAgIHRoaXMucHJvcHMuZXZlbnRicmlkZ2VCcm9rZXIuc2VuZFZpYVNmbkNoYWluKFxuICAgICAgICAgICdkb2N1bWVudC1wcm9jZXNzaW5nLWZhaWxlZCcsXG4gICAgICAgICAge1xuICAgICAgICAgICAgZG9jdW1lbnRJZDogSnNvblBhdGguc3RyaW5nQXQoJyQuZG9jdW1lbnRJZCcpLFxuICAgICAgICAgICAgYnVja2V0OiBKc29uUGF0aC5zdHJpbmdBdCgnJC5idWNrZXQnKSxcbiAgICAgICAgICAgIGZpbGVuYW1lOiBKc29uUGF0aC5zdHJpbmdBdCgnJC5maWxlbmFtZScpLFxuICAgICAgICAgIH0sXG4gICAgICAgICksXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBmYWlsZWRDaGFpbjtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlTW92ZVRvUHJvY2Vzc2VkQ2hhaW4oKSB7XG4gICAgY29uc3QgcHJvY2Vzc2VkQ2hhaW4gPSBuZXcgQ2FsbEF3c1NlcnZpY2UodGhpcywgJ0NvcHlUb1Byb2Nlc3NlZCcsIHtcbiAgICAgIHNlcnZpY2U6ICdzMycsXG4gICAgICBhY3Rpb246ICdjb3B5T2JqZWN0JyxcbiAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgQnVja2V0OiBKc29uUGF0aC5zdHJpbmdBdCgnJC5idWNrZXQnKSxcbiAgICAgICAgQ29weVNvdXJjZTogSnNvblBhdGguZm9ybWF0KCd7fS97fScsIEpzb25QYXRoLnN0cmluZ0F0KCckLmJ1Y2tldCcpLCBKc29uUGF0aC5zdHJpbmdBdCgnJC5rZXknKSksXG4gICAgICAgIEtleTogSnNvblBhdGguZm9ybWF0KCdwcm9jZXNzZWQve30nLCBKc29uUGF0aC5zdHJpbmdBdCgnJC5maWxlbmFtZScpKSxcbiAgICAgIH0sXG4gICAgICBpYW1SZXNvdXJjZXM6IFtgJHt0aGlzLmJ1Y2tldC5idWNrZXRBcm59LypgXSxcbiAgICAgIHJlc3VsdFBhdGg6IEpzb25QYXRoLkRJU0NBUkQsXG4gICAgfSkubmV4dChcbiAgICAgIG5ldyBDYWxsQXdzU2VydmljZSh0aGlzLCAnRGVsZXRlRnJvbVJhd1N1Y2Nlc3MnLCB7XG4gICAgICAgIHNlcnZpY2U6ICdzMycsXG4gICAgICAgIGFjdGlvbjogJ2RlbGV0ZU9iamVjdCcsXG4gICAgICAgIHBhcmFtZXRlcnM6IHtcbiAgICAgICAgICBCdWNrZXQ6IEpzb25QYXRoLnN0cmluZ0F0KCckLmJ1Y2tldCcpLFxuICAgICAgICAgIEtleTogSnNvblBhdGguc3RyaW5nQXQoJyQua2V5JyksXG4gICAgICAgIH0sXG4gICAgICAgIGlhbVJlc291cmNlczogW2Ake3RoaXMuYnVja2V0LmJ1Y2tldEFybn0vKmBdLFxuICAgICAgICByZXN1bHRQYXRoOiBKc29uUGF0aC5ESVNDQVJELFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIGlmICh0aGlzLnByb3BzLmV2ZW50YnJpZGdlQnJva2VyKSB7XG4gICAgICBwcm9jZXNzZWRDaGFpbi5uZXh0KFxuICAgICAgICB0aGlzLnByb3BzLmV2ZW50YnJpZGdlQnJva2VyLnNlbmRWaWFTZm5DaGFpbihcbiAgICAgICAgICAnZG9jdW1lbnQtcHJvY2Vzc2VkLXN1Y2Nlc3NmdWwnLFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIGRvY3VtZW50SWQ6IEpzb25QYXRoLnN0cmluZ0F0KCckLmRvY3VtZW50SWQnKSxcbiAgICAgICAgICAgIGJ1Y2tldDogSnNvblBhdGguc3RyaW5nQXQoJyQuYnVja2V0JyksXG4gICAgICAgICAgICBmaWxlbmFtZTogSnNvblBhdGguc3RyaW5nQXQoJyQuZmlsZW5hbWUnKSxcbiAgICAgICAgICAgIGNsYXNzaWZpY2F0aW9uOiBKc29uUGF0aC5zdHJpbmdBdCgnJC5jbGFzc2lmaWNhdGlvblJlc3VsdC5kb2N1bWVudENsYXNzaWZpY2F0aW9uJyksXG4gICAgICAgICAgfSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZENoYWluO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY3MoKTogSU1ldHJpY1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgZG9jdW1lbnQgY2xhc3NpZmljYXRpb24gc3RlcCBvZiB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqICoqQ1JJVElDQUwqKjogTXVzdCBzZXQgYG91dHB1dFBhdGhgIHRvIHByZXNlcnZlIHdvcmtmbG93IHN0YXRlIGZvciBzdWJzZXF1ZW50IHN0ZXBzLlxuICAgKiBUaGUgY2xhc3NpZmljYXRpb24gcmVzdWx0IHNob3VsZCBiZSBhdmFpbGFibGUgYXQgYCQuY2xhc3NpZmljYXRpb25SZXN1bHRgIGZvciBEeW5hbW9EQiBzdG9yYWdlLlxuICAgKlxuICAgKiBAcmV0dXJucyBTdGVwIEZ1bmN0aW9ucyB0YXNrIGZvciBkb2N1bWVudCBjbGFzc2lmaWNhdGlvblxuICAgKi9cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGNsYXNzaWZpY2F0aW9uU3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZTtcblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgZG9jdW1lbnQgcHJvY2Vzc2luZyBzdGVwIG9mIHRoZSB3b3JrZmxvdy5cbiAgICpcbiAgICogKipDUklUSUNBTCoqOiBNdXN0IHNldCBgb3V0cHV0UGF0aGAgdG8gcHJlc2VydmUgd29ya2Zsb3cgc3RhdGUgZm9yIHN1YnNlcXVlbnQgc3RlcHMuXG4gICAqIFRoZSBleHRyYWN0aW9uIHJlc3VsdCBzaG91bGQgYmUgYXZhaWxhYmxlIGF0IGAkLnByb2Nlc3NpbmdSZXN1bHRgIGZvciBEeW5hbW9EQiBzdG9yYWdlLlxuICAgKlxuICAgKiBAcmV0dXJucyBTdGVwIEZ1bmN0aW9ucyB0YXNrIGZvciBkb2N1bWVudCBleHRyYWN0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcHJvY2Vzc2luZ1N0ZXAoKTogRG9jdW1lbnRQcm9jZXNzaW5nU3RlcFR5cGU7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgdGhlIG9wdGlvbmFsIGRvY3VtZW50IGVucmljaG1lbnQgc3RlcCBvZiB0aGUgd29ya2Zsb3cuXG4gICAqXG4gICAqICoqQ1JJVElDQUwqKjogSWYgaW1wbGVtZW50ZWQsIG11c3Qgc2V0IGBvdXRwdXRQYXRoYCB0byBwcmVzZXJ2ZSB3b3JrZmxvdyBzdGF0ZS5cbiAgICogVGhlIGVucmljaG1lbnQgcmVzdWx0IHNob3VsZCBiZSBhdmFpbGFibGUgYXQgYCQuZW5yaWNoZWRSZXN1bHRgIGZvciBEeW5hbW9EQiBzdG9yYWdlLlxuICAgKlxuICAgKiBAcmV0dXJucyBTdGVwIEZ1bmN0aW9ucyB0YXNrIGZvciBkb2N1bWVudCBlbnJpY2htZW50LCBvciB1bmRlZmluZWQgdG8gc2tpcCB0aGlzIHN0ZXBcbiAgICovXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBlbnJpY2htZW50U3RlcCgpOiBEb2N1bWVudFByb2Nlc3NpbmdTdGVwVHlwZSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogRGVmaW5lcyB0aGUgb3B0aW9uYWwgcG9zdC1wcm9jZXNzaW5nIHN0ZXAgb2YgdGhlIHdvcmtmbG93LlxuICAgKlxuICAgKiAqKkNSSVRJQ0FMKio6IElmIGltcGxlbWVudGVkLCBtdXN0IHNldCBgb3V0cHV0UGF0aGAgdG8gcHJlc2VydmUgd29ya2Zsb3cgc3RhdGUuXG4gICAqIFRoZSBwb3N0LXByb2Nlc3NpbmcgcmVzdWx0IHNob3VsZCBiZSBhdmFpbGFibGUgYXQgYCQucG9zdFByb2Nlc3NlZFJlc3VsdGAgZm9yIER5bmFtb0RCIHN0b3JhZ2UuXG4gICAqXG4gICAqIEByZXR1cm5zIFN0ZXAgRnVuY3Rpb25zIHRhc2sgZm9yIHBvc3QtcHJvY2Vzc2luZywgb3IgdW5kZWZpbmVkIHRvIHNraXAgdGhpcyBzdGVwXG4gICAqL1xuICBwcm90ZWN0ZWQgYWJzdHJhY3QgcG9zdFByb2Nlc3NpbmdTdGVwKCk6IERvY3VtZW50UHJvY2Vzc2luZ1N0ZXBUeXBlIHwgdW5kZWZpbmVkO1xufVxuIl19