@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,432 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
4
+ const assertions_1 = require("aws-cdk-lib/assertions");
5
+ const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
6
+ const aws_kms_1 = require("aws-cdk-lib/aws-kms");
7
+ const aws_rds_1 = require("aws-cdk-lib/aws-rds");
8
+ const aws_secretsmanager_1 = require("aws-cdk-lib/aws-secretsmanager");
9
+ const cdk_nag_1 = require("cdk-nag");
10
+ const data_loader_1 = require("../data-loader");
11
+ // Create app and stack
12
+ const app = new aws_cdk_lib_1.App();
13
+ const stack = new aws_cdk_lib_1.Stack(app, 'TestStack', {
14
+ env: {
15
+ account: '123456789012',
16
+ region: 'us-east-1',
17
+ },
18
+ });
19
+ // Create KMS key for encryption at rest
20
+ const encryptionKey = new aws_kms_1.Key(stack, 'EncryptionKey', {
21
+ enableKeyRotation: true,
22
+ description: 'KMS key for DataLoader encryption at rest',
23
+ });
24
+ // Create VPC with Flow Logs to fix AwsSolutions-VPC7
25
+ const vpc = new aws_ec2_1.Vpc(stack, 'TestVpc', {
26
+ maxAzs: 2,
27
+ });
28
+ // Add VPC Flow Logs to fix AwsSolutions-VPC7
29
+ new aws_ec2_1.FlowLog(stack, 'VpcFlowLog', {
30
+ resourceType: aws_ec2_1.FlowLogResourceType.fromVpc(vpc),
31
+ trafficType: aws_ec2_1.FlowLogTrafficType.ALL,
32
+ });
33
+ // Create security group for database access
34
+ const dbSecurityGroup = new aws_ec2_1.SecurityGroup(stack, 'DatabaseSecurityGroup', {
35
+ vpc: vpc,
36
+ description: 'Security group for DataLoader database access',
37
+ allowAllOutbound: false,
38
+ });
39
+ // Create database credentials secret
40
+ const dbSecret = new aws_secretsmanager_1.Secret(stack, 'DatabaseSecret', {
41
+ description: 'Database credentials for DataLoader',
42
+ generateSecretString: {
43
+ secretStringTemplate: JSON.stringify({ username: 'postgres' }),
44
+ generateStringKey: 'password',
45
+ excludeCharacters: '"@/\\',
46
+ },
47
+ encryptionKey: encryptionKey,
48
+ });
49
+ // Create Aurora PostgreSQL cluster for testing
50
+ const dbCluster = new aws_rds_1.DatabaseCluster(stack, 'TestDatabaseCluster', {
51
+ engine: aws_rds_1.DatabaseClusterEngine.auroraPostgres({
52
+ version: aws_rds_1.AuroraPostgresEngineVersion.VER_15_4,
53
+ }),
54
+ vpc: vpc,
55
+ credentials: {
56
+ username: 'postgres',
57
+ password: dbSecret.secretValueFromJson('password'),
58
+ },
59
+ defaultDatabaseName: 'testdb',
60
+ securityGroups: [dbSecurityGroup],
61
+ storageEncryptionKey: encryptionKey,
62
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY, // For test environment
63
+ writer: aws_rds_1.ClusterInstance.provisioned('writer', {
64
+ instanceType: aws_ec2_1.InstanceType.of(aws_ec2_1.InstanceClass.T3, aws_ec2_1.InstanceSize.MEDIUM),
65
+ }),
66
+ });
67
+ // Create DataLoader construct
68
+ const dataLoader = new data_loader_1.DataLoader(stack, 'DataLoader', {
69
+ databaseConfig: {
70
+ engine: data_loader_1.DatabaseEngine.POSTGRESQL,
71
+ cluster: dbCluster,
72
+ secret: dbSecret,
73
+ databaseName: 'testdb',
74
+ vpc: vpc,
75
+ securityGroup: dbSecurityGroup,
76
+ },
77
+ fileInputs: [
78
+ {
79
+ filePath: 's3://test-bucket/schema.sql',
80
+ fileType: data_loader_1.FileType.SQL,
81
+ executionOrder: 1,
82
+ },
83
+ {
84
+ filePath: 's3://test-bucket/data.sql',
85
+ fileType: data_loader_1.FileType.SQL,
86
+ executionOrder: 2,
87
+ },
88
+ ],
89
+ removalPolicy: aws_cdk_lib_1.RemovalPolicy.DESTROY, // For test environment
90
+ });
91
+ // Add CDK Nag suppressions for acceptable violations
92
+ // Suppress VPC-related warnings for test environment
93
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/TestVpc', [
94
+ {
95
+ id: 'AwsSolutions-VPC7',
96
+ reason: 'VPC Flow Logs are added separately in the test setup',
97
+ },
98
+ ]);
99
+ // Suppress RDS-related warnings for test environment
100
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/TestDatabaseCluster', [
101
+ {
102
+ id: 'AwsSolutions-RDS2',
103
+ reason: 'Database encryption is enabled with customer-managed KMS key',
104
+ },
105
+ {
106
+ id: 'AwsSolutions-RDS3',
107
+ reason: 'Multi-AZ disabled for test environment cost optimization',
108
+ },
109
+ {
110
+ id: 'AwsSolutions-RDS6',
111
+ reason: 'IAM database authentication not required for this use case',
112
+ },
113
+ {
114
+ id: 'AwsSolutions-RDS10',
115
+ reason: 'Deletion protection disabled for test environment to allow cleanup',
116
+ },
117
+ {
118
+ id: 'AwsSolutions-RDS11',
119
+ reason: 'Default port acceptable within VPC security boundaries',
120
+ },
121
+ {
122
+ id: 'AwsSolutions-RDS14',
123
+ reason: 'Backtrack not available for PostgreSQL engine',
124
+ },
125
+ {
126
+ id: 'AwsSolutions-RDS16',
127
+ reason: 'Performance Insights disabled for cost optimization in test environment',
128
+ },
129
+ ]);
130
+ // Suppress Secrets Manager warnings
131
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DatabaseSecret', [
132
+ {
133
+ id: 'AwsSolutions-SMG4',
134
+ reason: 'Secret rotation not required for test environment',
135
+ },
136
+ ]);
137
+ // Suppress S3 bucket warnings for DataLoader bucket
138
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderBucket', [
139
+ {
140
+ id: 'AwsSolutions-S1',
141
+ reason: 'S3 access logging not required for internal data loading bucket',
142
+ },
143
+ {
144
+ id: 'AwsSolutions-S2',
145
+ reason: 'S3 bucket public read access is blocked by default configuration',
146
+ },
147
+ {
148
+ id: 'AwsSolutions-S3',
149
+ reason: 'SSL-only access is enforced through bucket policy',
150
+ },
151
+ {
152
+ id: 'AwsSolutions-S10',
153
+ reason: 'MFA delete not required for data loading bucket',
154
+ },
155
+ ]);
156
+ // Suppress S3 bucket policy warnings
157
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderBucket/Policy', [
158
+ {
159
+ id: 'AwsSolutions-S10',
160
+ reason: 'SSL-only access policy is enforced for data loading bucket security',
161
+ },
162
+ ]);
163
+ // Suppress Lambda function warnings for DataLoader processor
164
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderProcessor', [
165
+ {
166
+ id: 'AwsSolutions-L1',
167
+ reason: 'Lambda runtime version is managed at deployment time',
168
+ },
169
+ ]);
170
+ // Suppress security group warnings for DataLoader processor
171
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderProcessorSecurityGroup', [
172
+ {
173
+ id: 'AwsSolutions-EC23',
174
+ reason: 'Lambda security group allows all outbound traffic for AWS service access and dependency downloads',
175
+ },
176
+ ]);
177
+ // Suppress IAM role warnings for DataLoader processor
178
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderProcessor/ServiceRole', [
179
+ {
180
+ id: 'AwsSolutions-IAM4',
181
+ reason: 'AWSLambdaVPCAccessExecutionRole is required for VPC Lambda functions',
182
+ appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole'],
183
+ },
184
+ {
185
+ id: 'AwsSolutions-IAM5',
186
+ reason: 'Lambda function needs CloudWatch Logs permissions with wildcard for log stream creation',
187
+ appliesTo: ['Resource::arn:<AWS::Partition>:logs:*:*:log-group:/aws/lambda/*:*'],
188
+ },
189
+ ]);
190
+ // Suppress IAM policy warnings for DataLoader processor
191
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderProcessor/ServiceRole/DefaultPolicy', [
192
+ {
193
+ id: 'AwsSolutions-IAM5',
194
+ reason: 'Lambda function needs S3 read permissions for data loading files',
195
+ appliesTo: [
196
+ 'Action::s3:GetObject*',
197
+ 'Action::s3:GetBucket*',
198
+ 'Action::s3:List*',
199
+ ],
200
+ },
201
+ {
202
+ id: 'AwsSolutions-IAM5',
203
+ reason: 'Lambda function needs access to all objects in the data loading bucket',
204
+ appliesTo: ['Resource::<DataLoaderDataLoaderBucketF99DADE2.Arn>/*'],
205
+ },
206
+ ]);
207
+ // Suppress Step Functions warnings
208
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderStateMachine', [
209
+ {
210
+ id: 'AwsSolutions-SF1',
211
+ reason: 'Step Functions logging configuration is environment-specific',
212
+ },
213
+ {
214
+ id: 'AwsSolutions-SF2',
215
+ reason: 'X-Ray tracing configuration is environment-specific',
216
+ },
217
+ ]);
218
+ // Suppress Step Functions role warnings
219
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderStateMachine/Role', [
220
+ {
221
+ id: 'AwsSolutions-IAM5',
222
+ reason: 'Step Functions needs to invoke Lambda functions with specific permissions',
223
+ appliesTo: ['Resource::<DataLoaderDataLoaderProcessor*>'],
224
+ },
225
+ ]);
226
+ // Suppress Step Functions role policy warnings
227
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/DataLoaderStateMachine/Role/DefaultPolicy', [
228
+ {
229
+ id: 'AwsSolutions-IAM5',
230
+ reason: 'Step Functions needs to invoke the DataLoader processor Lambda function',
231
+ appliesTo: ['Resource::<DataLoaderDataLoaderProcessor693D75D2.Arn>:*'],
232
+ },
233
+ ]);
234
+ // Suppress custom resource Lambda warnings
235
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/StateMachineExecutionTrigger', [
236
+ {
237
+ id: 'AwsSolutions-L1',
238
+ reason: 'Custom resource Lambda runtime version is managed at deployment time',
239
+ },
240
+ ]);
241
+ // Suppress custom resource IAM warnings for the dedicated role
242
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/StateMachineExecutionTriggerRole', [
243
+ {
244
+ id: 'AwsSolutions-IAM4',
245
+ reason: 'AWSLambdaBasicExecutionRole is the standard minimal policy for Lambda execution',
246
+ appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'],
247
+ },
248
+ {
249
+ id: 'AwsSolutions-IAM5',
250
+ reason: 'Custom resource needs Step Functions execution permissions with wildcard for execution ARNs. ' +
251
+ 'Execution ARNs include dynamic execution names that cannot be predetermined.',
252
+ appliesTo: ['Resource::<DataLoaderDataLoaderStateMachine2071C3DC>:*'],
253
+ },
254
+ ]);
255
+ // Suppress custom resource provider warnings
256
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/StateMachineExecutionProvider', [
257
+ {
258
+ id: 'AwsSolutions-L1',
259
+ reason: 'Custom resource provider Lambda runtime version is managed at deployment time',
260
+ },
261
+ ]);
262
+ // Suppress custom resource provider IAM warnings
263
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/StateMachineExecutionProvider/framework-onEvent/ServiceRole', [
264
+ {
265
+ id: 'AwsSolutions-IAM4',
266
+ reason: 'AWSLambdaBasicExecutionRole is the standard minimal policy for Lambda execution',
267
+ appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'],
268
+ },
269
+ ]);
270
+ // Suppress custom resource provider policy warnings
271
+ cdk_nag_1.NagSuppressions.addResourceSuppressionsByPath(stack, '/TestStack/DataLoader/StateMachineExecutionProvider/framework-onEvent/ServiceRole/DefaultPolicy', [
272
+ {
273
+ id: 'AwsSolutions-IAM5',
274
+ reason: 'Custom resource needs Step Functions execution permissions',
275
+ appliesTo: ['Resource::<DataLoaderStateMachineExecutionTrigger94199E00.Arn>:*'],
276
+ },
277
+ ]);
278
+ // Suppress bucket deployment warnings if present
279
+ cdk_nag_1.NagSuppressions.addResourceSuppressions(stack, [
280
+ {
281
+ id: 'AwsSolutions-IAM4',
282
+ reason: 'CDK managed bucket deployment resources use AWS managed policies',
283
+ appliesTo: ['Policy::arn:<AWS::Partition>:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'],
284
+ },
285
+ {
286
+ id: 'AwsSolutions-IAM5',
287
+ reason: 'Bucket deployment requires wildcard permissions for S3 operations',
288
+ appliesTo: ['Resource::*'],
289
+ },
290
+ {
291
+ id: 'AwsSolutions-L1',
292
+ reason: 'CDK managed bucket deployment Lambda runtime is managed by CDK',
293
+ },
294
+ ], true);
295
+ // Apply CDK Nag checks
296
+ aws_cdk_lib_1.Aspects.of(app).add(new cdk_nag_1.AwsSolutionsChecks({ verbose: true }));
297
+ // Synthesize the stack
298
+ assertions_1.Template.fromStack(stack);
299
+ // Check for unsuppressed warnings and errors
300
+ const warnings = assertions_1.Annotations.fromStack(stack).findWarning('*', assertions_1.Match.stringLikeRegexp('AwsSolutions-.*'));
301
+ const errors = assertions_1.Annotations.fromStack(stack).findError('*', assertions_1.Match.stringLikeRegexp('AwsSolutions-.*'));
302
+ // Test: DataLoader construct is properly created
303
+ test('DataLoader construct is created successfully', () => {
304
+ expect(dataLoader).toBeDefined();
305
+ expect(dataLoader.node.id).toBe('DataLoader');
306
+ expect(dataLoader.bucket).toBeDefined();
307
+ expect(dataLoader.stateMachine).toBeDefined();
308
+ expect(dataLoader.processorFunction).toBeDefined();
309
+ expect(dataLoader.customResourceProvider).toBeDefined();
310
+ expect(dataLoader.executionTrigger).toBeDefined();
311
+ });
312
+ // Test: DataLoader has expected properties
313
+ test('DataLoader has expected properties', () => {
314
+ expect(dataLoader.bucket.bucketName).toBeDefined();
315
+ expect(dataLoader.stateMachine.stateMachineArn).toBeDefined();
316
+ expect(dataLoader.processorFunction.functionArn).toBeDefined();
317
+ });
318
+ // Test: Template contains expected DataLoader resources
319
+ test('Template contains expected DataLoader resources', () => {
320
+ const template = assertions_1.Template.fromStack(stack);
321
+ // Verify S3 bucket exists with encryption
322
+ template.hasResourceProperties('AWS::S3::Bucket', {
323
+ BucketEncryption: {
324
+ ServerSideEncryptionConfiguration: [
325
+ {
326
+ ServerSideEncryptionByDefault: {
327
+ SSEAlgorithm: 'AES256',
328
+ },
329
+ },
330
+ ],
331
+ },
332
+ PublicAccessBlockConfiguration: {
333
+ BlockPublicAcls: true,
334
+ BlockPublicPolicy: true,
335
+ IgnorePublicAcls: true,
336
+ RestrictPublicBuckets: true,
337
+ },
338
+ });
339
+ // Verify Lambda function exists with VPC configuration
340
+ template.hasResourceProperties('AWS::Lambda::Function', {
341
+ Runtime: 'python3.13',
342
+ VpcConfig: {
343
+ SecurityGroupIds: assertions_1.Match.anyValue(),
344
+ SubnetIds: assertions_1.Match.anyValue(),
345
+ },
346
+ });
347
+ // Verify Step Functions state machine exists
348
+ template.hasResourceProperties('AWS::StepFunctions::StateMachine', {
349
+ DefinitionString: assertions_1.Match.anyValue(),
350
+ });
351
+ // Verify Aurora cluster exists with encryption
352
+ template.hasResourceProperties('AWS::RDS::DBCluster', {
353
+ Engine: 'aurora-postgresql',
354
+ StorageEncrypted: true,
355
+ });
356
+ // Verify custom resource exists
357
+ template.hasResourceProperties('AWS::CloudFormation::CustomResource', {
358
+ ServiceToken: assertions_1.Match.anyValue(),
359
+ });
360
+ });
361
+ // Test: Security configurations are properly applied
362
+ test('Security configurations are properly applied', () => {
363
+ const template = assertions_1.Template.fromStack(stack);
364
+ // Verify KMS key exists with rotation enabled
365
+ template.hasResourceProperties('AWS::KMS::Key', {
366
+ EnableKeyRotation: true,
367
+ });
368
+ // Verify VPC Flow Logs exist
369
+ template.hasResourceProperties('AWS::EC2::FlowLog', {
370
+ ResourceType: 'VPC',
371
+ TrafficType: 'ALL',
372
+ });
373
+ // Verify Secrets Manager secret exists with KMS encryption
374
+ template.hasResourceProperties('AWS::SecretsManager::Secret', {
375
+ KmsKeyId: assertions_1.Match.anyValue(),
376
+ });
377
+ // Verify security group exists
378
+ template.hasResourceProperties('AWS::EC2::SecurityGroup', {
379
+ GroupDescription: 'Security group for DataLoader database access',
380
+ });
381
+ // Verify Lambda security group exists
382
+ template.hasResourceProperties('AWS::EC2::SecurityGroup', {
383
+ GroupDescription: 'Security group for DataLoader processor Lambda function',
384
+ });
385
+ });
386
+ // Test: IAM permissions are properly configured
387
+ test('IAM permissions are properly configured', () => {
388
+ const template = assertions_1.Template.fromStack(stack);
389
+ // Verify Lambda execution role exists
390
+ template.hasResourceProperties('AWS::IAM::Role', {
391
+ AssumeRolePolicyDocument: {
392
+ Statement: [
393
+ {
394
+ Action: 'sts:AssumeRole',
395
+ Effect: 'Allow',
396
+ Principal: {
397
+ Service: 'lambda.amazonaws.com',
398
+ },
399
+ },
400
+ ],
401
+ },
402
+ });
403
+ // Verify Step Functions role exists
404
+ template.hasResourceProperties('AWS::IAM::Role', {
405
+ AssumeRolePolicyDocument: {
406
+ Statement: [
407
+ {
408
+ Action: 'sts:AssumeRole',
409
+ Effect: 'Allow',
410
+ Principal: {
411
+ Service: 'states.amazonaws.com',
412
+ },
413
+ },
414
+ ],
415
+ },
416
+ });
417
+ });
418
+ // Test: No unsuppressed warnings
419
+ test('No unsuppressed warnings', () => {
420
+ if (warnings.length > 0) {
421
+ console.log('CDK Nag Warnings:', JSON.stringify(warnings, null, 2));
422
+ }
423
+ expect(warnings).toHaveLength(0);
424
+ });
425
+ // Test: No unsuppressed errors
426
+ test('No unsuppressed errors', () => {
427
+ if (errors.length > 0) {
428
+ console.log('CDK Nag Errors:', JSON.stringify(errors, null, 2));
429
+ }
430
+ expect(errors).toHaveLength(0);
431
+ });
432
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YS1sb2FkZXItbmFnLnRlc3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi91c2UtY2FzZXMvdXRpbGl0aWVzL3Rlc3RzL2RhdGEtbG9hZGVyLW5hZy50ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkNBQWlFO0FBQ2pFLHVEQUFzRTtBQUN0RSxpREFBc0o7QUFDdEosaURBQTBDO0FBQzFDLGlEQUEySDtBQUMzSCx1RUFBd0Q7QUFDeEQscUNBQThEO0FBQzlELGdEQUFzRTtBQUV0RSx1QkFBdUI7QUFDdkIsTUFBTSxHQUFHLEdBQUcsSUFBSSxpQkFBRyxFQUFFLENBQUM7QUFDdEIsTUFBTSxLQUFLLEdBQUcsSUFBSSxtQkFBSyxDQUFDLEdBQUcsRUFBRSxXQUFXLEVBQUU7SUFDeEMsR0FBRyxFQUFFO1FBQ0gsT0FBTyxFQUFFLGNBQWM7UUFDdkIsTUFBTSxFQUFFLFdBQVc7S0FDcEI7Q0FDRixDQUFDLENBQUM7QUFFSCx3Q0FBd0M7QUFDeEMsTUFBTSxhQUFhLEdBQUcsSUFBSSxhQUFHLENBQUMsS0FBSyxFQUFFLGVBQWUsRUFBRTtJQUNwRCxpQkFBaUIsRUFBRSxJQUFJO0lBQ3ZCLFdBQVcsRUFBRSwyQ0FBMkM7Q0FDekQsQ0FBQyxDQUFDO0FBRUgscURBQXFEO0FBQ3JELE1BQU0sR0FBRyxHQUFHLElBQUksYUFBRyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUU7SUFDcEMsTUFBTSxFQUFFLENBQUM7Q0FDVixDQUFDLENBQUM7QUFFSCw2Q0FBNkM7QUFDN0MsSUFBSSxpQkFBTyxDQUFDLEtBQUssRUFBRSxZQUFZLEVBQUU7SUFDL0IsWUFBWSxFQUFFLDZCQUFtQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUM7SUFDOUMsV0FBVyxFQUFFLDRCQUFrQixDQUFDLEdBQUc7Q0FDcEMsQ0FBQyxDQUFDO0FBRUgsNENBQTRDO0FBQzVDLE1BQU0sZUFBZSxHQUFHLElBQUksdUJBQWEsQ0FBQyxLQUFLLEVBQUUsdUJB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J2F3cy1jZGstbGliJztcbmltcG9ydCB7IFRlbXBsYXRlLCBBbm5vdGF0aW9ucywgTWF0Y2ggfSBmcm9tICdhd3MtY2RrLWxpYi9hc3NlcnRpb25zJztcbmltcG9ydCB7IFZwYywgRmxvd0xvZywgRmxvd0xvZ1Jlc291cmNlVHlwZSwgRmxvd0xvZ1RyYWZmaWNUeXBlLCBTZWN1cml0eUdyb3VwLCBJbnN0YW5jZVR5cGUsIEluc3RhbmNlQ2xhc3MsIEluc3RhbmNlU2l6ZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgS2V5IH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWttcyc7XG5pbXBvcnQgeyBEYXRhYmFzZUNsdXN0ZXIsIERhdGFiYXNlQ2x1c3RlckVuZ2luZSwgQXVyb3JhUG9zdGdyZXNFbmdpbmVWZXJzaW9uLCBDbHVzdGVySW5zdGFuY2UgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtcmRzJztcbmltcG9ydCB7IFNlY3JldCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1zZWNyZXRzbWFuYWdlcic7XG5pbXBvcnQgeyBBd3NTb2x1dGlvbnNDaGVja3MsIE5hZ1N1cHByZXNzaW9ucyB9IGZyb20gJ2Nkay1uYWcnO1xuaW1wb3J0IHsgRGF0YUxvYWRlciwgRGF0YWJhc2VFbmdpbmUsIEZpbGVUeXBlIH0gZnJvbSAnLi4vZGF0YS1sb2FkZXInO1xuXG4vLyBDcmVhdGUgYXBwIGFuZCBzdGFja1xuY29uc3QgYXBwID0gbmV3IEFwcCgpO1xuY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soYXBwLCAnVGVzdFN0YWNrJywge1xuICBlbnY6IHtcbiAgICBhY2NvdW50OiAnMTIzNDU2Nzg5MDEyJyxcbiAgICByZWdpb246ICd1cy1lYXN0LTEnLFxuICB9LFxufSk7XG5cbi8vIENyZWF0ZSBLTVMga2V5IGZvciBlbmNyeXB0aW9uIGF0IHJlc3RcbmNvbnN0IGVuY3J5cHRpb25LZXkgPSBuZXcgS2V5KHN0YWNrLCAnRW5jcnlwdGlvbktleScsIHtcbiAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gIGRlc2NyaXB0aW9uOiAnS01TIGtleSBmb3IgRGF0YUxvYWRlciBlbmNyeXB0aW9uIGF0IHJlc3QnLFxufSk7XG5cbi8vIENyZWF0ZSBWUEMgd2l0aCBGbG93IExvZ3MgdG8gZml4IEF3c1NvbHV0aW9ucy1WUEM3XG5jb25zdCB2cGMgPSBuZXcgVnBjKHN0YWNrLCAnVGVzdFZwYycsIHtcbiAgbWF4QXpzOiAyLFxufSk7XG5cbi8vIEFkZCBWUEMgRmxvdyBMb2dzIHRvIGZpeCBBd3NTb2x1dGlvbnMtVlBDN1xubmV3IEZsb3dMb2coc3RhY2ssICdWcGNGbG93TG9nJywge1xuICByZXNvdXJjZVR5cGU6IEZsb3dMb2dSZXNvdXJjZVR5cGUuZnJvbVZwYyh2cGMpLFxuICB0cmFmZmljVHlwZTogRmxvd0xvZ1RyYWZmaWNUeXBlLkFMTCxcbn0pO1xuXG4vLyBDcmVhdGUgc2VjdXJpdHkgZ3JvdXAgZm9yIGRhdGFiYXNlIGFjY2Vzc1xuY29uc3QgZGJTZWN1cml0eUdyb3VwID0gbmV3IFNlY3VyaXR5R3JvdXAoc3RhY2ssICdEYXRhYmFzZVNlY3VyaXR5R3JvdXAnLCB7XG4gIHZwYzogdnBjLFxuICBkZXNjcmlwdGlvbjogJ1NlY3VyaXR5IGdyb3VwIGZvciBEYXRhTG9hZGVyIGRhdGFiYXNlIGFjY2VzcycsXG4gIGFsbG93QWxsT3V0Ym91bmQ6IGZhbHNlLFxufSk7XG5cbi8vIENyZWF0ZSBkYXRhYmFzZSBjcmVkZW50aWFscyBzZWNyZXRcbmNvbnN0IGRiU2VjcmV0ID0gbmV3IFNlY3JldChzdGFjaywgJ0RhdGFiYXNlU2VjcmV0Jywge1xuICBkZXNjcmlwdGlvbjogJ0RhdGFiYXNlIGNyZWRlbnRpYWxzIGZvciBEYXRhTG9hZGVyJyxcbiAgZ2VuZXJhdGVTZWNyZXRTdHJpbmc6IHtcbiAgICBzZWNyZXRTdHJpbmdUZW1wbGF0ZTogSlNPTi5zdHJpbmdpZnkoeyB1c2VybmFtZTogJ3Bvc3RncmVzJyB9KSxcbiAgICBnZW5lcmF0ZVN0cmluZ0tleTogJ3Bhc3N3b3JkJyxcbiAgICBleGNsdWRlQ2hhcmFjdGVyczogJ1wiQC9cXFxcJyxcbiAgfSxcbiAgZW5jcnlwdGlvbktleTogZW5jcnlwdGlvbktleSxcbn0pO1xuXG4vLyBDcmVhdGUgQXVyb3JhIFBvc3RncmVTUUwgY2x1c3RlciBmb3IgdGVzdGluZ1xuY29uc3QgZGJDbHVzdGVyID0gbmV3IERhdGFiYXNlQ2x1c3RlcihzdGFjaywgJ1Rlc3REYXRhYmFzZUNsdXN0ZXInLCB7XG4gIGVuZ2luZTogRGF0YWJhc2VDbHVzdGVyRW5naW5lLmF1cm9yYVBvc3RncmVzKHtcbiAgICB2ZXJzaW9uOiBBdXJvcmFQb3N0Z3Jlc0VuZ2luZVZlcnNpb24uVkVSXzE1XzQsXG4gIH0pLFxuICB2cGM6IHZwYyxcbiAgY3JlZGVudGlhbHM6IHtcbiAgICB1c2VybmFtZTogJ3Bvc3RncmVzJyxcbiAgICBwYXNzd29yZDogZGJTZWNyZXQuc2VjcmV0VmFsdWVGcm9tSnNvbigncGFzc3dvcmQnKSxcbiAgfSxcbiAgZGVmYXVsdERhdGFiYXNlTmFtZTogJ3Rlc3RkYicsXG4gIHNlY3VyaXR5R3JvdXBzOiBbZGJTZWN1cml0eUdyb3VwXSxcbiAgc3RvcmFnZUVuY3J5cHRpb25LZXk6IGVuY3J5cHRpb25LZXksXG4gIHJlbW92YWxQb2xpY3k6IFJlbW92YWxQb2xpY3kuREVTVFJPWSwgLy8gRm9yIHRlc3QgZW52aXJvbm1lbnRcbiAgd3JpdGVyOiBDbHVzdGVySW5zdGFuY2UucHJvdmlzaW9uZWQoJ3dyaXRlcicsIHtcbiAgICBpbnN0YW5jZVR5cGU6IEluc3RhbmNlVHlwZS5vZihJbnN0YW5jZUNsYXNzLlQzLCBJbnN0YW5jZVNpemUuTUVESVVNKSxcbiAgfSksXG59KTtcblxuLy8gQ3JlYXRlIERhdGFMb2FkZXIgY29uc3RydWN0XG5jb25zdCBkYXRhTG9hZGVyID0gbmV3IERhdGFMb2FkZXIoc3RhY2ssICdEYXRhTG9hZGVyJywge1xuICBkYXRhYmFzZUNvbmZpZzoge1xuICAgIGVuZ2luZTogRGF0YWJhc2VFbmdpbmUuUE9TVEdSRVNRTCxcbiAgICBjbHVzdGVyOiBkYkNsdXN0ZXIsXG4gICAgc2VjcmV0OiBkYlNlY3JldCxcbiAgICBkYXRhYmFzZU5hbWU6ICd0ZXN0ZGInLFxuICAgIHZwYzogdnBjLFxuICAgIHNlY3VyaXR5R3JvdXA6IGRiU2VjdXJpdHlHcm91cCxcbiAgfSxcbiAgZmlsZUlucHV0czogW1xuICAgIHtcbiAgICAgIGZpbGVQYXRoOiAnczM6Ly90ZXN0LWJ1Y2tldC9zY2hlbWEuc3FsJyxcbiAgICAgIGZpbGVUeXBlOiBGaWxlVHlwZS5TUUwsXG4gICAgICBleGVjdXRpb25PcmRlcjogMSxcbiAgICB9LFxuICAgIHtcbiAgICAgIGZpbGVQYXRoOiAnczM6Ly90ZXN0LWJ1Y2tldC9kYXRhLnNxbCcsXG4gICAgICBmaWxlVHlwZTogRmlsZVR5cGUuU1FMLFxuICAgICAgZXhlY3V0aW9uT3JkZXI6IDIsXG4gICAgfSxcbiAgXSxcbiAgcmVtb3ZhbFBvbGljeTogUmVtb3ZhbFBvbGljeS5ERVNUUk9ZLCAvLyBGb3IgdGVzdCBlbnZpcm9ubWVudFxufSk7XG5cbi8vIEFkZCBDREsgTmFnIHN1cHByZXNzaW9ucyBmb3IgYWNjZXB0YWJsZSB2aW9sYXRpb25zXG5cbi8vIFN1cHByZXNzIFZQQy1yZWxhdGVkIHdhcm5pbmdzIGZvciB0ZXN0IGVudmlyb25tZW50XG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL1Rlc3RWcGMnLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1WUEM3JyxcbiAgICByZWFzb246ICdWUEMgRmxvdyBMb2dzIGFyZSBhZGRlZCBzZXBhcmF0ZWx5IGluIHRoZSB0ZXN0IHNldHVwJyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBSRFMtcmVsYXRlZCB3YXJuaW5ncyBmb3IgdGVzdCBlbnZpcm9ubWVudFxuTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zQnlQYXRoKHN0YWNrLCAnL1Rlc3RTdGFjay9UZXN0RGF0YWJhc2VDbHVzdGVyJywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUkRTMicsXG4gICAgcmVhc29uOiAnRGF0YWJhc2UgZW5jcnlwdGlvbiBpcyBlbmFibGVkIHdpdGggY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5JyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVJEUzMnLFxuICAgIHJlYXNvbjogJ011bHRpLUFaIGRpc2FibGVkIGZvciB0ZXN0IGVudmlyb25tZW50IGNvc3Qgb3B0aW1pemF0aW9uJyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVJEUzYnLFxuICAgIHJlYXNvbjogJ0lBTSBkYXRhYmFzZSBhdXRoZW50aWNhdGlvbiBub3QgcmVxdWlyZWQgZm9yIHRoaXMgdXNlIGNhc2UnLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUkRTMTAnLFxuICAgIHJlYXNvbjogJ0RlbGV0aW9uIHByb3RlY3Rpb24gZGlzYWJsZWQgZm9yIHRlc3QgZW52aXJvbm1lbnQgdG8gYWxsb3cgY2xlYW51cCcsXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1SRFMxMScsXG4gICAgcmVhc29uOiAnRGVmYXVsdCBwb3J0IGFjY2VwdGFibGUgd2l0aGluIFZQQyBzZWN1cml0eSBib3VuZGFyaWVzJyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVJEUzE0JyxcbiAgICByZWFzb246ICdCYWNrdHJhY2sgbm90IGF2YWlsYWJsZSBmb3IgUG9zdGdyZVNRTCBlbmdpbmUnLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUkRTMTYnLFxuICAgIHJlYXNvbjogJ1BlcmZvcm1hbmNlIEluc2lnaHRzIGRpc2FibGVkIGZvciBjb3N0IG9wdGltaXphdGlvbiBpbiB0ZXN0IGVudmlyb25tZW50JyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBTZWNyZXRzIE1hbmFnZXIgd2FybmluZ3Ncbk5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9uc0J5UGF0aChzdGFjaywgJy9UZXN0U3RhY2svRGF0YWJhc2VTZWNyZXQnLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1TTUc0JyxcbiAgICByZWFzb246ICdTZWNyZXQgcm90YXRpb24gbm90IHJlcXVpcmVkIGZvciB0ZXN0IGVudmlyb25tZW50JyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBTMyBidWNrZXQgd2FybmluZ3MgZm9yIERhdGFMb2FkZXIgYnVja2V0XG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlckJ1Y2tldCcsIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVMxJyxcbiAgICByZWFzb246ICdTMyBhY2Nlc3MgbG9nZ2luZyBub3QgcmVxdWlyZWQgZm9yIGludGVybmFsIGRhdGEgbG9hZGluZyBidWNrZXQnLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUzInLFxuICAgIHJlYXNvbjogJ1MzIGJ1Y2tldCBwdWJsaWMgcmVhZCBhY2Nlc3MgaXMgYmxvY2tlZCBieSBkZWZhdWx0IGNvbmZpZ3VyYXRpb24nLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUzMnLFxuICAgIHJlYXNvbjogJ1NTTC1vbmx5IGFjY2VzcyBpcyBlbmZvcmNlZCB0aHJvdWdoIGJ1Y2tldCBwb2xpY3knLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUzEwJyxcbiAgICByZWFzb246ICdNRkEgZGVsZXRlIG5vdCByZXF1aXJlZCBmb3IgZGF0YSBsb2FkaW5nIGJ1Y2tldCcsXG4gIH0sXG5dKTtcblxuLy8gU3VwcHJlc3MgUzMgYnVja2V0IHBvbGljeSB3YXJuaW5nc1xuTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zQnlQYXRoKHN0YWNrLCAnL1Rlc3RTdGFjay9EYXRhTG9hZGVyL0RhdGFMb2FkZXJCdWNrZXQvUG9saWN5JywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtUzEwJyxcbiAgICByZWFzb246ICdTU0wtb25seSBhY2Nlc3MgcG9saWN5IGlzIGVuZm9yY2VkIGZvciBkYXRhIGxvYWRpbmcgYnVja2V0IHNlY3VyaXR5JyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBMYW1iZGEgZnVuY3Rpb24gd2FybmluZ3MgZm9yIERhdGFMb2FkZXIgcHJvY2Vzc29yXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlclByb2Nlc3NvcicsIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUwxJyxcbiAgICByZWFzb246ICdMYW1iZGEgcnVudGltZSB2ZXJzaW9uIGlzIG1hbmFnZWQgYXQgZGVwbG95bWVudCB0aW1lJyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBzZWN1cml0eSBncm91cCB3YXJuaW5ncyBmb3IgRGF0YUxvYWRlciBwcm9jZXNzb3Jcbk5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9uc0J5UGF0aChzdGFjaywgJy9UZXN0U3RhY2svRGF0YUxvYWRlci9EYXRhTG9hZGVyUHJvY2Vzc29yU2VjdXJpdHlHcm91cCcsIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUVDMjMnLFxuICAgIHJlYXNvbjogJ0xhbWJkYSBzZWN1cml0eSBncm91cCBhbGxvd3MgYWxsIG91dGJvdW5kIHRyYWZmaWMgZm9yIEFXUyBzZXJ2aWNlIGFjY2VzcyBhbmQgZGVwZW5kZW5jeSBkb3dubG9hZHMnLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIElBTSByb2xlIHdhcm5pbmdzIGZvciBEYXRhTG9hZGVyIHByb2Nlc3NvclxuTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zQnlQYXRoKHN0YWNrLCAnL1Rlc3RTdGFjay9EYXRhTG9hZGVyL0RhdGFMb2FkZXJQcm9jZXNzb3IvU2VydmljZVJvbGUnLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU00JyxcbiAgICByZWFzb246ICdBV1NMYW1iZGFWUENBY2Nlc3NFeGVjdXRpb25Sb2xlIGlzIHJlcXVpcmVkIGZvciBWUEMgTGFtYmRhIGZ1bmN0aW9ucycsXG4gICAgYXBwbGllc1RvOiBbJ1BvbGljeTo6YXJuOjxBV1M6OlBhcnRpdGlvbj46aWFtOjphd3M6cG9saWN5L3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFWUENBY2Nlc3NFeGVjdXRpb25Sb2xlJ10sXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU01JyxcbiAgICByZWFzb246ICdMYW1iZGEgZnVuY3Rpb24gbmVlZHMgQ2xvdWRXYXRjaCBMb2dzIHBlcm1pc3Npb25zIHdpdGggd2lsZGNhcmQgZm9yIGxvZyBzdHJlYW0gY3JlYXRpb24nLFxuICAgIGFwcGxpZXNUbzogWydSZXNvdXJjZTo6YXJuOjxBV1M6OlBhcnRpdGlvbj46bG9nczoqOio6bG9nLWdyb3VwOi9hd3MvbGFtYmRhLyo6KiddLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIElBTSBwb2xpY3kgd2FybmluZ3MgZm9yIERhdGFMb2FkZXIgcHJvY2Vzc29yXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlclByb2Nlc3Nvci9TZXJ2aWNlUm9sZS9EZWZhdWx0UG9saWN5JywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgcmVhc29uOiAnTGFtYmRhIGZ1bmN0aW9uIG5lZWRzIFMzIHJlYWQgcGVybWlzc2lvbnMgZm9yIGRhdGEgbG9hZGluZyBmaWxlcycsXG4gICAgYXBwbGllc1RvOiBbXG4gICAgICAnQWN0aW9uOjpzMzpHZXRPYmplY3QqJyxcbiAgICAgICdBY3Rpb246OnMzOkdldEJ1Y2tldConLFxuICAgICAgJ0FjdGlvbjo6czM6TGlzdConLFxuICAgIF0sXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU01JyxcbiAgICByZWFzb246ICdMYW1iZGEgZnVuY3Rpb24gbmVlZHMgYWNjZXNzIHRvIGFsbCBvYmplY3RzIGluIHRoZSBkYXRhIGxvYWRpbmcgYnVja2V0JyxcbiAgICBhcHBsaWVzVG86IFsnUmVzb3VyY2U6OjxEYXRhTG9hZGVyRGF0YUxvYWRlckJ1Y2tldEY5OURBREUyLkFybj4vKiddLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIFN0ZXAgRnVuY3Rpb25zIHdhcm5pbmdzXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlclN0YXRlTWFjaGluZScsIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVNGMScsXG4gICAgcmVhc29uOiAnU3RlcCBGdW5jdGlvbnMgbG9nZ2luZyBjb25maWd1cmF0aW9uIGlzIGVudmlyb25tZW50LXNwZWNpZmljJyxcbiAgfSxcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLVNGMicsXG4gICAgcmVhc29uOiAnWC1SYXkgdHJhY2luZyBjb25maWd1cmF0aW9uIGlzIGVudmlyb25tZW50LXNwZWNpZmljJyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBTdGVwIEZ1bmN0aW9ucyByb2xlIHdhcm5pbmdzXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlclN0YXRlTWFjaGluZS9Sb2xlJywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgcmVhc29uOiAnU3RlcCBGdW5jdGlvbnMgbmVlZHMgdG8gaW52b2tlIExhbWJkYSBmdW5jdGlvbnMgd2l0aCBzcGVjaWZpYyBwZXJtaXNzaW9ucycsXG4gICAgYXBwbGllc1RvOiBbJ1Jlc291cmNlOjo8RGF0YUxvYWRlckRhdGFMb2FkZXJQcm9jZXNzb3IqPiddLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIFN0ZXAgRnVuY3Rpb25zIHJvbGUgcG9saWN5IHdhcm5pbmdzXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvRGF0YUxvYWRlclN0YXRlTWFjaGluZS9Sb2xlL0RlZmF1bHRQb2xpY3knLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU01JyxcbiAgICByZWFzb246ICdTdGVwIEZ1bmN0aW9ucyBuZWVkcyB0byBpbnZva2UgdGhlIERhdGFMb2FkZXIgcHJvY2Vzc29yIExhbWJkYSBmdW5jdGlvbicsXG4gICAgYXBwbGllc1RvOiBbJ1Jlc291cmNlOjo8RGF0YUxvYWRlckRhdGFMb2FkZXJQcm9jZXNzb3I2OTNENzVEMi5Bcm4+OionXSxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBjdXN0b20gcmVzb3VyY2UgTGFtYmRhIHdhcm5pbmdzXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvU3RhdGVNYWNoaW5lRXhlY3V0aW9uVHJpZ2dlcicsIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUwxJyxcbiAgICByZWFzb246ICdDdXN0b20gcmVzb3VyY2UgTGFtYmRhIHJ1bnRpbWUgdmVyc2lvbiBpcyBtYW5hZ2VkIGF0IGRlcGxveW1lbnQgdGltZScsXG4gIH0sXG5dKTtcblxuLy8gU3VwcHJlc3MgY3VzdG9tIHJlc291cmNlIElBTSB3YXJuaW5ncyBmb3IgdGhlIGRlZGljYXRlZCByb2xlXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvU3RhdGVNYWNoaW5lRXhlY3V0aW9uVHJpZ2dlclJvbGUnLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU00JyxcbiAgICByZWFzb246ICdBV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUgaXMgdGhlIHN0YW5kYXJkIG1pbmltYWwgcG9saWN5IGZvciBMYW1iZGEgZXhlY3V0aW9uJyxcbiAgICBhcHBsaWVzVG86IFsnUG9saWN5Ojphcm46PEFXUzo6UGFydGl0aW9uPjppYW06OmF3czpwb2xpY3kvc2VydmljZS1yb2xlL0FXU0xhbWJkYUJhc2ljRXhlY3V0aW9uUm9sZSddLFxuICB9LFxuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgcmVhc29uOiAnQ3VzdG9tIHJlc291cmNlIG5lZWRzIFN0ZXAgRnVuY3Rpb25zIGV4ZWN1dGlvbiBwZXJtaXNzaW9ucyB3aXRoIHdpbGRjYXJkIGZvciBleGVjdXRpb24gQVJOcy4gJyArXG4gICAgICAgICAgICAnRXhlY3V0aW9uIEFSTnMgaW5jbHVkZSBkeW5hbWljIGV4ZWN1dGlvbiBuYW1lcyB0aGF0IGNhbm5vdCBiZSBwcmVkZXRlcm1pbmVkLicsXG4gICAgYXBwbGllc1RvOiBbJ1Jlc291cmNlOjo8RGF0YUxvYWRlckRhdGFMb2FkZXJTdGF0ZU1hY2hpbmUyMDcxQzNEQz46KiddLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIGN1c3RvbSByZXNvdXJjZSBwcm92aWRlciB3YXJuaW5nc1xuTmFnU3VwcHJlc3Npb25zLmFkZFJlc291cmNlU3VwcHJlc3Npb25zQnlQYXRoKHN0YWNrLCAnL1Rlc3RTdGFjay9EYXRhTG9hZGVyL1N0YXRlTWFjaGluZUV4ZWN1dGlvblByb3ZpZGVyJywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtTDEnLFxuICAgIHJlYXNvbjogJ0N1c3RvbSByZXNvdXJjZSBwcm92aWRlciBMYW1iZGEgcnVudGltZSB2ZXJzaW9uIGlzIG1hbmFnZWQgYXQgZGVwbG95bWVudCB0aW1lJyxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIgSUFNIHdhcm5pbmdzXG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnNCeVBhdGgoc3RhY2ssICcvVGVzdFN0YWNrL0RhdGFMb2FkZXIvU3RhdGVNYWNoaW5lRXhlY3V0aW9uUHJvdmlkZXIvZnJhbWV3b3JrLW9uRXZlbnQvU2VydmljZVJvbGUnLCBbXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU00JyxcbiAgICByZWFzb246ICdBV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUgaXMgdGhlIHN0YW5kYXJkIG1pbmltYWwgcG9saWN5IGZvciBMYW1iZGEgZXhlY3V0aW9uJyxcbiAgICBhcHBsaWVzVG86IFsnUG9saWN5Ojphcm46PEFXUzo6UGFydGl0aW9uPjppYW06OmF3czpwb2xpY3kvc2VydmljZS1yb2xlL0FXU0xhbWJkYUJhc2ljRXhlY3V0aW9uUm9sZSddLFxuICB9LFxuXSk7XG5cbi8vIFN1cHByZXNzIGN1c3RvbSByZXNvdXJjZSBwcm92aWRlciBwb2xpY3kgd2FybmluZ3Ncbk5hZ1N1cHByZXNzaW9ucy5hZGRSZXNvdXJjZVN1cHByZXNzaW9uc0J5UGF0aChzdGFjaywgJy9UZXN0U3RhY2svRGF0YUxvYWRlci9TdGF0ZU1hY2hpbmVFeGVjdXRpb25Qcm92aWRlci9mcmFtZXdvcmstb25FdmVudC9TZXJ2aWNlUm9sZS9EZWZhdWx0UG9saWN5JywgW1xuICB7XG4gICAgaWQ6ICdBd3NTb2x1dGlvbnMtSUFNNScsXG4gICAgcmVhc29uOiAnQ3VzdG9tIHJlc291cmNlIG5lZWRzIFN0ZXAgRnVuY3Rpb25zIGV4ZWN1dGlvbiBwZXJtaXNzaW9ucycsXG4gICAgYXBwbGllc1RvOiBbJ1Jlc291cmNlOjo8RGF0YUxvYWRlclN0YXRlTWFjaGluZUV4ZWN1dGlvblRyaWdnZXI5NDE5OUUwMC5Bcm4+OionXSxcbiAgfSxcbl0pO1xuXG4vLyBTdXBwcmVzcyBidWNrZXQgZGVwbG95bWVudCB3YXJuaW5ncyBpZiBwcmVzZW50XG5OYWdTdXBwcmVzc2lvbnMuYWRkUmVzb3VyY2VTdXBwcmVzc2lvbnMoc3RhY2ssIFtcbiAge1xuICAgIGlkOiAnQXdzU29sdXRpb25zLUlBTTQnLFxuICAgIHJlYXNvbjogJ0NESyBtYW5hZ2VkIGJ1Y2tldCBkZXBsb3ltZW50IHJlc291cmNlcyB1c2UgQVdTIG1hbmFnZWQgcG9saWNpZXMnLFxuICAgIGFwcGxpZXNUbzogWydQb2xpY3k6OmFybjo8QVdTOjpQYXJ0aXRpb24+OmlhbTo6YXdzOnBvbGljeS9zZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJ10sXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1JQU01JyxcbiAgICByZWFzb246ICdCdWNrZXQgZGVwbG95bWVudCByZXF1aXJlcyB3aWxkY2FyZCBwZXJtaXNzaW9ucyBmb3IgUzMgb3BlcmF0aW9ucycsXG4gICAgYXBwbGllc1RvOiBbJ1Jlc291cmNlOjoqJ10sXG4gIH0sXG4gIHtcbiAgICBpZDogJ0F3c1NvbHV0aW9ucy1MMScsXG4gICAgcmVhc29uOiAnQ0RLIG1hbmFnZWQgYnVja2V0IGRlcGxveW1lbnQgTGFtYmRhIHJ1bnRpbWUgaXMgbWFuYWdlZCBieSBDREsnLFxuICB9LFxuXSwgdHJ1ZSk7XG5cbi8vIEFwcGx5IENESyBOYWcgY2hlY2tzXG5Bc3BlY3RzLm9mKGFwcCkuYWRkKG5ldyBBd3NTb2x1dGlvbnNDaGVja3MoeyB2ZXJib3NlOiB0cnVlIH0pKTtcblxuLy8gU3ludGhlc2l6ZSB0aGUgc3RhY2tcblRlbXBsYXRlLmZyb21TdGFjayhzdGFjayk7XG5cbi8vIENoZWNrIGZvciB1bnN1cHByZXNzZWQgd2FybmluZ3MgYW5kIGVycm9yc1xuY29uc3Qgd2FybmluZ3MgPSBBbm5vdGF0aW9ucy5mcm9tU3RhY2soc3RhY2spLmZpbmRXYXJuaW5nKCcqJywgTWF0Y2guc3RyaW5nTGlrZVJlZ2V4cCgnQXdzU29sdXRpb25zLS4qJykpO1xuY29uc3QgZXJyb3JzID0gQW5ub3RhdGlvbnMuZnJvbVN0YWNrKHN0YWNrKS5maW5kRXJyb3IoJyonLCBNYXRjaC5zdHJpbmdMaWtlUmVnZXhwKCdBd3NTb2x1dGlvbnMtLionKSk7XG5cbi8vIFRlc3Q6IERhdGFMb2FkZXIgY29uc3RydWN0IGlzIHByb3Blcmx5IGNyZWF0ZWRcbnRlc3QoJ0RhdGFMb2FkZXIgY29uc3RydWN0IGlzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JywgKCkgPT4ge1xuICBleHBlY3QoZGF0YUxvYWRlcikudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGRhdGFMb2FkZXIubm9kZS5pZCkudG9CZSgnRGF0YUxvYWRlcicpO1xuICBleHBlY3QoZGF0YUxvYWRlci5idWNrZXQpLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChkYXRhTG9hZGVyLnN0YXRlTWFjaGluZSkudG9CZURlZmluZWQoKTtcbiAgZXhwZWN0KGRhdGFMb2FkZXIucHJvY2Vzc29yRnVuY3Rpb24pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChkYXRhTG9hZGVyLmN1c3RvbVJlc291cmNlUHJvdmlkZXIpLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChkYXRhTG9hZGVyLmV4ZWN1dGlvblRyaWdnZXIpLnRvQmVEZWZpbmVkKCk7XG59KTtcblxuLy8gVGVzdDogRGF0YUxvYWRlciBoYXMgZXhwZWN0ZWQgcHJvcGVydGllc1xudGVzdCgnRGF0YUxvYWRlciBoYXMgZXhwZWN0ZWQgcHJvcGVydGllcycsICgpID0+IHtcbiAgZXhwZWN0KGRhdGFMb2FkZXIuYnVja2V0LmJ1Y2tldE5hbWUpLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChkYXRhTG9hZGVyLnN0YXRlTWFjaGluZS5zdGF0ZU1hY2hpbmVBcm4pLnRvQmVEZWZpbmVkKCk7XG4gIGV4cGVjdChkYXRhTG9hZGVyLnByb2Nlc3NvckZ1bmN0aW9uLmZ1bmN0aW9uQXJuKS50b0JlRGVmaW5lZCgpO1xufSk7XG5cbi8vIFRlc3Q6IFRlbXBsYXRlIGNvbnRhaW5zIGV4cGVjdGVkIERhdGFMb2FkZXIgcmVzb3VyY2VzXG50ZXN0KCdUZW1wbGF0ZSBjb250YWlucyBleHBlY3RlZCBEYXRhTG9hZGVyIHJlc291cmNlcycsICgpID0+IHtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gIC8vIFZlcmlmeSBTMyBidWNrZXQgZXhpc3RzIHdpdGggZW5jcnlwdGlvblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6UzM6OkJ1Y2tldCcsIHtcbiAgICBCdWNrZXRFbmNyeXB0aW9uOiB7XG4gICAgICBTZXJ2ZXJTaWRlRW5jcnlwdGlvbkNvbmZpZ3VyYXRpb246IFtcbiAgICAgICAge1xuICAgICAgICAgIFNlcnZlclNpZGVFbmNyeXB0aW9uQnlEZWZhdWx0OiB7XG4gICAgICAgICAgICBTU0VBbGdvcml0aG06ICdBRVMyNTYnLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0sXG4gICAgUHVibGljQWNjZXNzQmxvY2tDb25maWd1cmF0aW9uOiB7XG4gICAgICBCbG9ja1B1YmxpY0FjbHM6IHRydWUsXG4gICAgICBCbG9ja1B1YmxpY1BvbGljeTogdHJ1ZSxcbiAgICAgIElnbm9yZVB1YmxpY0FjbHM6IHRydWUsXG4gICAgICBSZXN0cmljdFB1YmxpY0J1Y2tldHM6IHRydWUsXG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gVmVyaWZ5IExhbWJkYSBmdW5jdGlvbiBleGlzdHMgd2l0aCBWUEMgY29uZmlndXJhdGlvblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6TGFtYmRhOjpGdW5jdGlvbicsIHtcbiAgICBSdW50aW1lOiAncHl0aG9uMy4xMycsXG4gICAgVnBjQ29uZmlnOiB7XG4gICAgICBTZWN1cml0eUdyb3VwSWRzOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgICAgU3VibmV0SWRzOiBNYXRjaC5hbnlWYWx1ZSgpLFxuICAgIH0sXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBTdGVwIEZ1bmN0aW9ucyBzdGF0ZSBtYWNoaW5lIGV4aXN0c1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U3RlcEZ1bmN0aW9uczo6U3RhdGVNYWNoaW5lJywge1xuICAgIERlZmluaXRpb25TdHJpbmc6IE1hdGNoLmFueVZhbHVlKCksXG4gIH0pO1xuXG4gIC8vIFZlcmlmeSBBdXJvcmEgY2x1c3RlciBleGlzdHMgd2l0aCBlbmNyeXB0aW9uXG4gIHRlbXBsYXRlLmhhc1Jlc291cmNlUHJvcGVydGllcygnQVdTOjpSRFM6OkRCQ2x1c3RlcicsIHtcbiAgICBFbmdpbmU6ICdhdXJvcmEtcG9zdGdyZXNxbCcsXG4gICAgU3RvcmFnZUVuY3J5cHRlZDogdHJ1ZSxcbiAgfSk7XG5cbiAgLy8gVmVyaWZ5IGN1c3RvbSByZXNvdXJjZSBleGlzdHNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OkNsb3VkRm9ybWF0aW9uOjpDdXN0b21SZXNvdXJjZScsIHtcbiAgICBTZXJ2aWNlVG9rZW46IE1hdGNoLmFueVZhbHVlKCksXG4gIH0pO1xufSk7XG5cbi8vIFRlc3Q6IFNlY3VyaXR5IGNvbmZpZ3VyYXRpb25zIGFyZSBwcm9wZXJseSBhcHBsaWVkXG50ZXN0KCdTZWN1cml0eSBjb25maWd1cmF0aW9ucyBhcmUgcHJvcGVybHkgYXBwbGllZCcsICgpID0+IHtcbiAgY29uc3QgdGVtcGxhdGUgPSBUZW1wbGF0ZS5mcm9tU3RhY2soc3RhY2spO1xuXG4gIC8vIFZlcmlmeSBLTVMga2V5IGV4aXN0cyB3aXRoIHJvdGF0aW9uIGVuYWJsZWRcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OktNUzo6S2V5Jywge1xuICAgIEVuYWJsZUtleVJvdGF0aW9uOiB0cnVlLFxuICB9KTtcblxuICAvLyBWZXJpZnkgVlBDIEZsb3cgTG9ncyBleGlzdFxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6RUMyOjpGbG93TG9nJywge1xuICAgIFJlc291cmNlVHlwZTogJ1ZQQycsXG4gICAgVHJhZmZpY1R5cGU6ICdBTEwnLFxuICB9KTtcblxuICAvLyBWZXJpZnkgU2VjcmV0cyBNYW5hZ2VyIHNlY3JldCBleGlzdHMgd2l0aCBLTVMgZW5jcnlwdGlvblxuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6U2VjcmV0c01hbmFnZXI6OlNlY3JldCcsIHtcbiAgICBLbXNLZXlJZDogTWF0Y2guYW55VmFsdWUoKSxcbiAgfSk7XG5cbiAgLy8gVmVyaWZ5IHNlY3VyaXR5IGdyb3VwIGV4aXN0c1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6RUMyOjpTZWN1cml0eUdyb3VwJywge1xuICAgIEdyb3VwRGVzY3JpcHRpb246ICdTZWN1cml0eSBncm91cCBmb3IgRGF0YUxvYWRlciBkYXRhYmFzZSBhY2Nlc3MnLFxuICB9KTtcblxuICAvLyBWZXJpZnkgTGFtYmRhIHNlY3VyaXR5IGdyb3VwIGV4aXN0c1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6RUMyOjpTZWN1cml0eUdyb3VwJywge1xuICAgIEdyb3VwRGVzY3JpcHRpb246ICdTZWN1cml0eSBncm91cCBmb3IgRGF0YUxvYWRlciBwcm9jZXNzb3IgTGFtYmRhIGZ1bmN0aW9uJyxcbiAgfSk7XG59KTtcblxuLy8gVGVzdDogSUFNIHBlcm1pc3Npb25zIGFyZSBwcm9wZXJseSBjb25maWd1cmVkXG50ZXN0KCdJQU0gcGVybWlzc2lvbnMgYXJlIHByb3Blcmx5IGNvbmZpZ3VyZWQnLCAoKSA9PiB7XG4gIGNvbnN0IHRlbXBsYXRlID0gVGVtcGxhdGUuZnJvbVN0YWNrKHN0YWNrKTtcblxuICAvLyBWZXJpZnkgTGFtYmRhIGV4ZWN1dGlvbiByb2xlIGV4aXN0c1xuICB0ZW1wbGF0ZS5oYXNSZXNvdXJjZVByb3BlcnRpZXMoJ0FXUzo6SUFNOjpSb2xlJywge1xuICAgIEFzc3VtZVJvbGVQb2xpY3lEb2N1bWVudDoge1xuICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBBY3Rpb246ICdzdHM6QXNzdW1lUm9sZScsXG4gICAgICAgICAgRWZmZWN0OiAnQWxsb3cnLFxuICAgICAgICAgIFByaW5jaXBhbDoge1xuICAgICAgICAgICAgU2VydmljZTogJ2xhbWJkYS5hbWF6b25hd3MuY29tJyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9LFxuICB9KTtcblxuICAvLyBWZXJpZnkgU3RlcCBGdW5jdGlvbnMgcm9sZSBleGlzdHNcbiAgdGVtcGxhdGUuaGFzUmVzb3VyY2VQcm9wZXJ0aWVzKCdBV1M6OklBTTo6Um9sZScsIHtcbiAgICBBc3N1bWVSb2xlUG9saWN5RG9jdW1lbnQ6IHtcbiAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgQWN0aW9uOiAnc3RzOkFzc3VtZVJvbGUnLFxuICAgICAgICAgIEVmZmVjdDogJ0FsbG93JyxcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIFNlcnZpY2U6ICdzdGF0ZXMuYW1hem9uYXdzLmNvbScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSxcbiAgfSk7XG59KTtcblxuLy8gVGVzdDogTm8gdW5zdXBwcmVzc2VkIHdhcm5pbmdzXG50ZXN0KCdObyB1bnN1cHByZXNzZWQgd2FybmluZ3MnLCAoKSA9PiB7XG4gIGlmICh3YXJuaW5ncy5sZW5ndGggPiAwKSB7XG4gICAgY29uc29sZS5sb2coJ0NESyBOYWcgV2FybmluZ3M6JywgSlNPTi5zdHJpbmdpZnkod2FybmluZ3MsIG51bGwsIDIpKTtcbiAgfVxuICBleHBlY3Qod2FybmluZ3MpLnRvSGF2ZUxlbmd0aCgwKTtcbn0pO1xuXG4vLyBUZXN0OiBObyB1bnN1cHByZXNzZWQgZXJyb3JzXG50ZXN0KCdObyB1bnN1cHByZXNzZWQgZXJyb3JzJywgKCkgPT4ge1xuICBpZiAoZXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zb2xlLmxvZygnQ0RLIE5hZyBFcnJvcnM6JywgSlNPTi5zdHJpbmdpZnkoZXJyb3JzLCBudWxsLCAyKSk7XG4gIH1cbiAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDApO1xufSk7XG4iXX0=
@@ -0,0 +1 @@
1
+ export {};