{
  "Resources": {
    "PreUpgradeExport": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "contentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
        "id": "ExportAll_QnABot_v7.3.14.json",
        "index": {"Fn::Sub": "${Var.QnaIndex}"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": "${EmbeddingsApi} ${EmbeddingsBedrockModelId} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn}"
        }
      }
    },
    "PreUpgradeExportMetrics": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "contentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
        "id": "ExportAll_QnABot_v7.3.14_metrics.json",
        "index": {"Fn::Sub": "${Var.MetricsIndex}"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": "${EmbeddingsApi} ${EmbeddingsBedrockModelId} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn}"
        }
      }
    },
    "PreUpgradeExportFeedback": {
      "Type": "Custom::PreUpgradeExport",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "bucket": {"Ref": "ExportBucket"},
        "contentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
        "id": "ExportAll_QnABot_v7.3.14_feedback.json",
        "index": {"Fn::Sub": "${Var.FeedbackIndex}"},
        "PRE_UPGRADE_EXPORT_TRIGGERS": {
          "Fn::Sub": "${EmbeddingsApi} ${EmbeddingsBedrockModelId} ${EmbeddingsLambdaDimensions} ${EmbeddingsLambdaArn}"
        }
      }
    },
    "AssetBucket": {
      "Type": "AWS::S3::Bucket",
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "VersioningConfiguration": {"Status": "Enabled"},
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/Assets/"]]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {"id": "F14", "reason": "AccessControl is deprecated."}
          ]
        },
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      }
    },
    "HTTPSOnlyAssetBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "AssetBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["AssetBucket", "Arn"]}, "/*"]
                  ]
                },
                {"Fn::Join": ["", [{"Fn::GetAtt": ["AssetBucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "AssetClean": {
      "Type": "Custom::S3Clean",
      "DependsOn": ["CFNInvokePolicy", "HTTPSOnlyAssetBucketPolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["S3Clean", "Arn"]},
        "Bucket": {"Ref": "AssetBucket"}
      }
    },
    "AssetZipVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v7.3.14", "/assets.zip"]]},
        "BuildDate": "2026-06-09T15:56:38.488Z"
      }
    },
    "AssetUnzip": {
      "Type": "Custom::S3Unzip",
      "DependsOn": ["AssetClean"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "SrcBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v7.3.14", "/assets.zip"]]},
        "DstBucket": {"Ref": "AssetBucket"},
        "version": {"Ref": "AssetZipVersion"}
      }
    },
    "MainAccessLogBucket": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "VersioningConfiguration": {"Status": "Enabled"},
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W35",
              "reason": "Access logging is not required for this Bucket."
            }
          ]
        },
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      }
    },
    "MainAccessLogsBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "DependsOn": "MainAccessLogBucket",
      "Properties": {
        "Bucket": {"Ref": "MainAccessLogBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "s3:PutObject",
              "Condition": {
                "ArnLike": {"aws:SourceArn": "arn:aws:s3:::*"},
                "Bool": {"aws:SecureTransport": "true"},
                "StringEquals": {"aws:SourceAccount": {"Ref": "AWS::AccountId"}}
              },
              "Effect": "Allow",
              "Principal": {"Service": "logging.s3.amazonaws.com"},
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["MainAccessLogBucket", "Arn"]}, "/*"]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["MainAccessLogBucket", "Arn"]}]
                  ]
                }
              ],
              "Sid": "S3ServerAccessLogsPolicy"
            },
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["MainAccessLogBucket", "Arn"]}, "/*"]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["MainAccessLogBucket", "Arn"]}]
                  ]
                }
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "ExportBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [
            {"NoncurrentVersionExpirationInDays": 1, "Status": "Enabled"},
            {
              "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 1},
              "Status": "Enabled"
            }
          ]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["GET"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/Export/"]]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain"
    },
    "HTTPSOnlyExportBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "ExportBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["ExportBucket", "Arn"]}, "/*"]
                  ]
                },
                {"Fn::Join": ["", [{"Fn::GetAtt": ["ExportBucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "ImportBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [{"ExpirationInDays": 1, "Status": "Enabled"}]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["PUT"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/Import/"]]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      }
    },
    "HTTPSOnlyImportBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "ImportBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["ImportBucket", "Arn"]}, "/*"]
                  ]
                },
                {"Fn::Join": ["", [{"Fn::GetAtt": ["ImportBucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "TestAllBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [{"ExpirationInDays": 1, "Status": "Enabled"}]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["GET"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/TestAll/"]]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      }
    },
    "HTTPSOnlyTestAllBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "TestAllBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["TestAllBucket", "Arn"]}, "/*"]
                  ]
                },
                {"Fn::Join": ["", [{"Fn::GetAtt": ["TestAllBucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "ContentDesignerOutputBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [{"ExpirationInDays": 1, "Status": "Enabled"}]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "CorsConfiguration": {
          "CorsRules": [
            {
              "AllowedHeaders": ["*"],
              "AllowedMethods": ["GET"],
              "AllowedOrigins": ["*"]
            }
          ]
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": [
              "",
              [{"Ref": "MainAccessLogBucket"}, "/ContentDesignerOutput/"]
            ]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        }
      }
    },
    "HTTPSOnlyContentDesignerOutputBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "ContentDesignerOutputBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [
                      {"Fn::GetAtt": ["ContentDesignerOutputBucket", "Arn"]},
                      "/*"
                    ]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["ContentDesignerOutputBucket", "Arn"]}]
                  ]
                }
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "ContentDesignerOutputClean": {
      "Type": "Custom::S3Clean",
      "DependsOn": ["CFNInvokePolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["S3Clean", "Arn"]},
        "Bucket": {"Ref": "ContentDesignerOutputBucket"}
      }
    },
    "VersionLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-VersionLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "VersionLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { S3Client, HeadObjectCommand } = require('@aws-sdk/client-s3');\n\nconst region = process.env.AWS_REGION;\nconst client = new S3Client({\n    customUserAgent: [\n        [`AWSSOLUTION/${process.env.SOLUTION_ID}/${process.env.SOLUTION_VERSION}`],\n        [`AWSSOLUTION-CAPABILITY/${process.env.SOLUTION_ID}-C023/${process.env.SOLUTION_VERSION}`],\n    ],\n    region,\n});\n\nconst SUCCESS = 'SUCCESS';\nconst FAILED = 'FAILED';\nconst https = require('https');\nconst { URL } = require('url');\n\nasync function send(event, context, responseStatus, responseData, physicalResourceId, noEcho) {\n    return new Promise((resolve, reject) => {\n        const responseBody = JSON.stringify({\n            Status: responseStatus,\n            Reason: `See the details in CloudWatch Log Stream: ${context.logStreamName}`,\n            PhysicalResourceId: physicalResourceId || context.logStreamName,\n            StackId: event.StackId,\n            RequestId: event.RequestId,\n            LogicalResourceId: event.LogicalResourceId,\n            NoEcho: noEcho || false,\n            Data: responseData,\n        });\n\n        console.log('Response body:\\n', responseBody);\n\n        const parsedUrl = new URL(event.ResponseURL);\n\n        const options = {\n            hostname: parsedUrl.hostname,\n            port: 443,\n            path: parsedUrl.pathname + parsedUrl.search,\n            method: 'PUT',\n            headers: {\n                'content-type': '',\n                'content-length': responseBody.length,\n            },\n        };\n\n        const request = https.request(options, (response) => {\n            console.log(`Status code: ${response.statusCode}`);\n            console.log(`Status message: ${response.statusMessage}`);\n            response.on('end', () => {\n                resolve();\n            });\n        });\n\n        request.on('error', (error) => {\n            console.log(`send(..) failed executing https.request(..): ${error}`);\n            reject(error);\n        });\n\n        request.write(responseBody);\n        request.end();\n    });\n}\n\nexports.handler = async function (event, context) {\n    console.log(JSON.stringify(event, null, 2));\n    if (event.RequestType !== 'Delete') {\n        const params = {\n            Bucket: event.ResourceProperties.Bucket,\n            Key: event.ResourceProperties.Key,\n        };\n        const headObjCmd = new HeadObjectCommand(params);\n        try {\n            const result = await client.send(headObjCmd);\n            await send(event, context, SUCCESS, {\n                version: result.VersionId ? result.VersionId : 1,\n            });\n        } catch (e) {\n            console.log(e);\n            await send(event, context, FAILED);\n        }\n    } else {\n        await send(event, context, SUCCESS);\n    }\n    context.done();\n};\n"
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "VersionLambdaLogGroup"}},
        "MemorySize": "3008",
        "Role": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 60,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "CFNVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["VersionLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/cfn.zip"},
        "BuildDate": "2026-06-09T15:56:38.489Z"
      }
    },
    "CFNLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-CFNLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "CFNLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Join": ["", ["qnabot-on-aws/v7.3.14", "/lambda/cfn.zip"]]
          },
          "S3ObjectVersion": {"Fn::GetAtt": ["CFNVersion", "version"]}
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "CFNLambdaLogGroup"}},
        "MemorySize": "3008",
        "Role": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 180,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "CFNInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [{"Fn::GetAtt": ["CFNLambda", "Arn"]}]
            }
          ]
        },
        "Roles": [{"Ref": "CFNLambdaRole"}]
      }
    },
    "CognitoDomain": {
      "Type": "Custom::CognitoDomain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"}
      }
    },
    "CognitoLoginClient": {
      "Type": "Custom::CognitoLogin",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "ClientId": {"Ref": "ClientClient"},
        "LoginCallbackUrls": [{"Fn::GetAtt": ["Urls", "Client"]}],
        "CSS": ".logo-customizable{max-width:60%;max-height:30%}.banner-customizable{padding:25px 0px 25px 0px;background-color:#d3d3d3}.label-customizable{font-weight:410}.textDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.idpDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.legalText-customizable{color:#747474;font-size:11px}.submitButton-customizable{font-size:14px;font-weight:bold;margin:20px 0px 10px 0px;height:40px;width:100%;color:#fff;background-color:#337ab7}.submitButton-customizable:hover{color:#fff;background-color:#286090}.errorMessage-customizable{padding:5px;font-size:14px;width:100%;background:#f5f5f5;border:2px solid #d64958;color:#d64958}.inputField-customizable{width:100%;height:34px;color:#555;background-color:#fff;border:1px solid #ccc}.inputField-customizable:focus{border-color:#66afe9;outline:0}.idpButton-customizable{height:41px;width:100%;text-align:center;margin-bottom:15px;color:#fff;background-color:#5bc0de;border-color:#46b8da}.idpButton-customizable:hover{color:#fff;background-color:#31b0d5}.socialButton-customizable{height:40px;text-align:left;width:100%;margin-bottom:15px}.redirect-customizable{text-align:center}.passwordCheck-notValid-customizable{color:#df3312}.passwordCheck-valid-customizable{color:#19bf00}.background-customizable{background-color:#fff}"
      }
    },
    "CognitoLoginDesigner": {
      "Type": "Custom::CognitoLogin",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "ClientId": {"Ref": "ClientDesigner"},
        "LoginCallbackUrls": [{"Fn::GetAtt": ["Urls", "Designer"]}],
        "LogoutCallbackUrls": [{"Fn::GetAtt": ["Urls", "Designer"]}],
        "CSS": ".logo-customizable{max-width:60%;max-height:30%}.banner-customizable{padding:25px 0px 25px 0px;background-color:#d3d3d3;margin-left:auto;margin-right:auto}.label-customizable{font-weight:410}.textDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.idpDescription-customizable{padding-top:10px;padding-bottom:10px;display:block;font-size:16px}.legalText-customizable{color:#747474;font-size:11px}.submitButton-customizable{font-size:14px;font-weight:bold;margin:20px 0px 10px 0px;height:40px;width:100%;color:#fff;background-color:#337ab7}.submitButton-customizable:hover{color:#fff;background-color:#286090}.errorMessage-customizable{padding:5px;font-size:14px;width:100%;background:#f5f5f5;border:2px solid #d64958;color:#d64958}.inputField-customizable{width:100%;height:34px;color:#555;background-color:#fff;border:1px solid #ccc}.inputField-customizable:focus{border-color:#66afe9;outline:0}.idpButton-customizable{height:41px;width:100%;text-align:center;margin-bottom:15px;color:#fff;background-color:#5bc0de;border-color:#46b8da}.idpButton-customizable:hover{color:#fff;background-color:#31b0d5}.socialButton-customizable{height:40px;text-align:left;width:100%;margin-bottom:15px}.redirect-customizable{text-align:center}.passwordCheck-notValid-customizable{color:#df3312}.passwordCheck-valid-customizable{color:#19bf00}.background-customizable{background-color:#fff}"
      }
    },
    "DesignerLogin": {
      "Type": "Custom::CognitoUrl",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "adad": "adaad",
        "ClientId": {"Ref": "ClientDesigner"},
        "Domain": {"Ref": "CognitoDomain"},
        "LoginRedirectUrl": {"Fn::GetAtt": ["Urls", "Designer"]},
        "response_type": "code"
      }
    },
    "ClientLogin": {
      "Type": "Custom::CognitoUrl",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "ClientId": {"Ref": "ClientClient"},
        "Domain": {"Ref": "CognitoDomain"},
        "LoginRedirectUrl": {"Fn::GetAtt": ["Urls", "Client"]},
        "response_type": "code"
      }
    },
    "User": {
      "Type": "AWS::Cognito::UserPoolUser",
      "DependsOn": [
        "SignupPermision",
        "MessagePermision",
        "OpenSearchDashboardsRoleAttachment",
        "RoleAttachment"
      ],
      "Properties": {
        "DesiredDeliveryMediums": ["EMAIL"],
        "UserAttributes": [{"Name": "email", "Value": {"Ref": "Email"}}],
        "Username": {"Ref": "Username"},
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "UserToGroup": {
      "Type": "AWS::Cognito::UserPoolUserToGroupAttachment",
      "Properties": {
        "GroupName": {"Ref": "Admins"},
        "Username": {"Ref": "User"},
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "IdPool": {
      "Type": "AWS::Cognito::IdentityPool",
      "Properties": {
        "IdentityPoolName": {
          "Fn::Join": ["-", ["QnaBotIdPool", {"Ref": "AWS::StackName"}]]
        },
        "AllowUnauthenticatedIdentities": true,
        "CognitoIdentityProviders": [
          {
            "ClientId": {"Ref": "ClientDesigner"},
            "ProviderName": {"Fn::GetAtt": ["UserPool", "ProviderName"]},
            "ServerSideTokenCheck": true
          },
          {
            "ClientId": {"Ref": "ClientClient"},
            "ProviderName": {"Fn::GetAtt": ["UserPool", "ProviderName"]},
            "ServerSideTokenCheck": true
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W57",
              "reason": "This IdentityPool has proper restrictions for unauthenticated users"
            }
          ]
        }
      }
    },
    "OpenSearchDashboardsIdPool": {
      "Type": "AWS::Cognito::IdentityPool",
      "Properties": {
        "IdentityPoolName": {
          "Fn::Join": [
            "-",
            ["OpenSearchDashboardsIdPool", {"Ref": "AWS::StackName"}]
          ]
        },
        "AllowUnauthenticatedIdentities": false
      }
    },
    "OpenSearchDashboardsRoleAttachment": {
      "Type": "Custom::CognitoRole",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "IdentityPoolId": {"Ref": "OpenSearchDashboardsIdPool"},
        "DomainName": {"Fn::GetAtt": ["ESVar", "ESDomain"]},
        "Roles": {
          "authenticated": {"Fn::GetAtt": ["UserRole", "Arn"]},
          "unauthenticated": {"Fn::GetAtt": ["UnauthenticatedRole", "Arn"]}
        },
        "RoleMappings": [
          {
            "ClientId": {
              "Fn::GetAtt": ["OpenSearchDashboardsClient", "ClientId"]
            },
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "Deny",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["OpenSearchDashboardsRole", "Arn"]}
                }
              ]
            }
          }
        ]
      }
    },
    "RoleAttachment": {
      "Type": "Custom::CognitoRole",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "IdentityPoolId": {"Ref": "IdPool"},
        "Roles": {
          "authenticated": {"Fn::GetAtt": ["UserRole", "Arn"]},
          "unauthenticated": {"Fn::GetAtt": ["UnauthenticatedRole", "Arn"]}
        },
        "RoleMappings": [
          {
            "ClientId": {"Ref": "ClientClient"},
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "AuthenticatedRole",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["UserRole", "Arn"]}
                }
              ]
            }
          },
          {
            "ClientId": {"Ref": "ClientDesigner"},
            "UserPool": {"Ref": "UserPool"},
            "Type": "Rules",
            "AmbiguousRoleResolution": "Deny",
            "RulesConfiguration": {
              "Rules": [
                {
                  "Claim": "cognito:groups",
                  "MatchType": "Contains",
                  "Value": "Admin",
                  "RoleARN": {"Fn::GetAtt": ["AdminRole", "Arn"]}
                }
              ]
            }
          }
        ]
      }
    },
    "UserPool": {
      "Type": "AWS::Cognito::UserPool",
      "Properties": {
        "UserPoolName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}]]
        },
        "AdminCreateUserConfig": {
          "AllowAdminCreateUserOnly": {"Fn::If": ["AdminSignUp", true, false]},
          "InviteMessageTemplate": {
            "EmailMessage": {
              "Fn::Sub": "<p>Hello {username},\n<p>Welcome to QnABot! Your temporary password is:\n<p>     {####}\n<p>\n<p>When the CloudFormation stack is COMPLETE, use the link below to log in to QnABot Content Designer, set your permanent password, and start building your bot!\n<p>     ${ApiUrl.Name}/pages/designer\n<p>\n<p>Good luck!\n<p>QnABot (www.amazon.com/qnabot)\n"
            },
            "EmailSubject": "Welcome to QnABot!"
          }
        },
        "AliasAttributes": ["email"],
        "AutoVerifiedAttributes": ["email"],
        "Schema": [
          {
            "Required": true,
            "Name": "email",
            "AttributeDataType": "String",
            "Mutable": true
          }
        ],
        "LambdaConfig": {
          "CustomMessage": {"Fn::GetAtt": ["MessageLambda", "Arn"]},
          "PreSignUp": {"Fn::GetAtt": ["SignupLambda", "Arn"]}
        }
      }
    },
    "OpenSearchDashboardsClient": {
      "Type": "Custom::ESCognitoClient",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "UserPool": {"Ref": "UserPool"},
        "DomainName": {"Fn::GetAtt": ["ESVar", "ESDomain"]}
      }
    },
    "ClientDesigner": {
      "Type": "AWS::Cognito::UserPoolClient",
      "Properties": {
        "ClientName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}, "designer"]]
        },
        "GenerateSecret": false,
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "ClientClient": {
      "Type": "AWS::Cognito::UserPoolClient",
      "Properties": {
        "ClientName": {
          "Fn::Join": ["-", ["UserPool", {"Ref": "AWS::StackName"}, "client"]]
        },
        "GenerateSecret": false,
        "UserPoolId": {"Ref": "UserPool"}
      }
    },
    "Users": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {"GroupName": "Users", "UserPoolId": {"Ref": "UserPool"}}
    },
    "Admins": {
      "Type": "AWS::Cognito::UserPoolGroup",
      "Properties": {"GroupName": "Admins", "UserPoolId": {"Ref": "UserPool"}}
    },
    "UsersTable": {
      "Type": "AWS::DynamoDB::Table",
      "Properties": {
        "BillingMode": "PAY_PER_REQUEST",
        "PointInTimeRecoverySpecification": {
          "PointInTimeRecoveryEnabled": true
        },
        "AttributeDefinitions": [
          {"AttributeName": "UserId", "AttributeType": "S"}
        ],
        "KeySchema": [{"AttributeName": "UserId", "KeyType": "HASH"}],
        "TimeToLiveSpecification": {"AttributeName": "ttl", "Enabled": true}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W74",
              "reason": "This DynamoDB table does not require CMK encryption store in KMS"
            }
          ]
        }
      }
    },
    "SettingsTable": {
      "Type": "AWS::DynamoDB::Table",
      "Properties": {
        "BillingMode": "PAY_PER_REQUEST",
        "PointInTimeRecoverySpecification": {
          "PointInTimeRecoveryEnabled": true
        },
        "SSESpecification": {"SSEEnabled": true},
        "AttributeDefinitions": [
          {"AttributeName": "SettingName", "AttributeType": "S"},
          {"AttributeName": "SettingCategory", "AttributeType": "S"}
        ],
        "KeySchema": [{"AttributeName": "SettingName", "KeyType": "HASH"}],
        "GlobalSecondaryIndexes": [
          {
            "IndexName": "SettingCategoryIndex",
            "KeySchema": [
              {"AttributeName": "SettingCategory", "KeyType": "HASH"}
            ],
            "Projection": {"ProjectionType": "ALL"}
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W74",
              "reason": "This DynamoDB table does not require CMK encryption store in KMS"
            }
          ]
        }
      }
    },
    "SettingsInitializer": {
      "Type": "Custom::SettingsInitializer",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "SettingsTable": {"Ref": "SettingsTable"},
        "ES_USE_KEYWORD_FILTERS": {
          "Fn::If": ["EmbeddingsEnable", "false", "true"]
        },
        "EMBEDDINGS_ENABLE": {"Fn::If": ["EmbeddingsEnable", "true", "false"]},
        "EMBEDDINGS_MAX_TOKEN_LIMIT": {
          "Fn::If": [
            "EmbeddingsBedrock",
            {
              "Fn::FindInMap": [
                "BedrockDefaults",
                {"Ref": "EmbeddingsBedrockModelId"},
                "MaxTokens"
              ]
            },
            ""
          ]
        },
        "EMBEDDINGS_SCORE_THRESHOLD": {
          "Fn::If": ["EmbeddingsBedrock", 0.7, 0.85]
        },
        "EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD": {
          "Fn::If": ["EmbeddingsBedrock", 0.65, 0.8]
        },
        "NATIVE_LANGUAGE": {"Ref": "Language"},
        "ALT_SEARCH_KENDRA_INDEXES": {"Ref": "AltSearchKendraIndexes"},
        "ALT_SEARCH_KENDRA_INDEX_AUTH": {"Ref": "AltSearchKendraIndexAuth"},
        "KENDRA_FAQ_INDEX": {"Ref": "KendraFaqIndexId"},
        "KENDRA_WEB_PAGE_INDEX": {"Ref": "KendraWebPageIndexId"},
        "LLM_API": {"Ref": "LLMApi"},
        "LLM_GENERATE_QUERY_ENABLE": {"Fn::If": ["LLMEnable", "true", "false"]},
        "LLM_QA_ENABLE": {"Fn::If": ["LLMEnable", "true", "false"]},
        "LLM_GENERATE_QUERY_PROMPT_TEMPLATE": "<br><br>Human: Here is a chat history in <chatHistory> tags:<br><chatHistory><br>{history}<br></chatHistory><br>Human: And here is a follow up question or statement from the human in <followUpMessage> tags:<br><followUpMessage><br>{input}<br></followUpMessage><br>Human: Rephrase the follow up question or statement as a standalone question or statement that makes sense without reading the chat history.<br><br>Assistant: Here is the rephrased follow up question or statement:",
        "LLM_GENERATE_QUERY_SYSTEM_PROMPT": "",
        "LLM_QA_PROMPT_TEMPLATE": "Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Write the answer in up to 5 complete sentences.<br><br>{context}<br><br>Question: {query}<br>Helpful Answer:",
        "LLM_QA_SYSTEM_PROMPT": "You are an AI assistant designed to disambiguate user queries.",
        "LLM_GENERATE_QUERY_MODEL_PARAMS": {
          "Fn::If": [
            "LLMBedrock",
            "{\\\"temperature\\\":0, \\\"maxTokens\\\":300, \\\"topP\\\":1}",
            "{}"
          ]
        },
        "LLM_QA_MODEL_PARAMS": {
          "Fn::If": [
            "LLMBedrock",
            "{\\\"temperature\\\":0, \\\"maxTokens\\\":300, \\\"topP\\\":1}",
            "{}"
          ]
        },
        "LLM_PROMPT_MAX_TOKEN_LIMIT": {"Fn::If": ["LLMBedrock", 100000, ""]},
        "LLM_QA_NO_HITS_REGEX": "(Sorry, I don't know|unable to assist you|i don't have enough context|i don't have enough information|i don't have any information|do not contain any information|do not contain information|i could not find an exact answer|no information in the search results|search results do not mention|search results do not provide specific|don't see any information in the provided search results|search results do not contain|no information in the provided search results|not find any information|search results did not contain|unable to respond|There is no mention of|documents do not mention anything|There is no information provided|reference passages do not mention|reference doesn't specify|could not find an answer to this question|the model cannot answer this question|none of the search results contain)",
        "KNOWLEDGE_BASE_PROMPT_TEMPLATE": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\\"Sorry, I don't know\\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: <question> $query$ </question> $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the <question> as concisely as possible. Assistant:",
        "EMBEDDINGS_MODEL_ID": {
          "Fn::If": [
            "EmbeddingsBedrock",
            {
              "Fn::FindInMap": [
                "BedrockDefaults",
                {"Ref": "EmbeddingsBedrockModelId"},
                "ModelID"
              ]
            },
            ""
          ]
        },
        "LLM_MODEL_ID": {
          "Fn::If": ["LLMBedrock", {"Ref": "LLMBedrockModelId"}, ""]
        },
        "KNOWLEDGE_BASE_MODEL_ID": {
          "Fn::If": [
            "BedrockKnowledgeBaseEnable",
            {"Ref": "BedrockKnowledgeBaseModel"},
            ""
          ]
        },
        "KNOWLEDGE_BASE_ID": {
          "Fn::If": [
            "BedrockKnowledgeBaseEnable",
            {"Ref": "BedrockKnowledgeBaseId"},
            ""
          ]
        },
        "LLM_STREAMING_ENABLED": {
          "Fn::If": ["StreamingEnabled", "true", "false"]
        },
        "STREAMING_TABLE": {
          "Fn::If": [
            "StreamingEnabled",
            {
              "Fn::GetAtt": ["StreamingStack", "Outputs.StreamingDynamoDbTable"]
            },
            ""
          ]
        },
        "DefaultSettingsParameter": {"Ref": "DefaultQnABotSettings"},
        "PrivateSettingsParameter": {"Ref": "PrivateQnABotSettings"},
        "CustomSettingsParameter": {"Ref": "CustomQnABotSettings"}
      }
    },
    "ExamplesStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "BuildExamples",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v7.3.14/templates/examples.json"
        },
        "Parameters": {
          "QnAType": {"Fn::GetAtt": ["Var", "QnAType"]},
          "QuizType": {"Fn::GetAtt": ["Var", "QuizType"]},
          "Index": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "ResponseBotStackName": {
            "Fn::GetAtt": ["Var", "ResponseBotStackName"]
          },
          "ESAddress": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v7.3.14",
          "FeedbackKinesisFirehose": {
            "Fn::GetAtt": ["FeedbackKinesisFirehose", "Arn"]
          },
          "FeedbackKinesisFirehoseName": {"Ref": "FeedbackKinesisFirehose"},
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNLambdaRole": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
          "S3Clean": {"Fn::GetAtt": ["S3Clean", "Arn"]},
          "ApiUrlName": {"Fn::GetAtt": ["ApiUrl", "Name"]},
          "AssetBucket": {"Ref": "AssetBucket"},
          "FulfillmentLambdaRole": {"Ref": "FulfillmentLambdaRole"},
          "QIDLambdaArn": {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
          "VPCSubnetIdList": {"Fn::Join": [",", {"Ref": "VPCSubnetIdList"}]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", {"Ref": "VPCSecurityGroupIdList"}]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "InstallLexResponseBots": {"Ref": "InstallLexResponseBots"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "LogRetentionPeriod": {"Ref": "LogRetentionPeriod"}
        }
      }
    },
    "ExportStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v7.3.14/templates/export.json"
        },
        "Parameters": {
          "SettingsTable": {"Ref": "SettingsTable"},
          "ContentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "S3Clean": {"Fn::GetAtt": ["S3Clean", "Arn"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v7.3.14",
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "ExportBucket": {"Ref": "ExportBucket"},
          "VPCSubnetIdList": {"Fn::Join": [",", {"Ref": "VPCSubnetIdList"}]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", {"Ref": "VPCSecurityGroupIdList"}]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "Api": {"Ref": "API"},
          "ApiRootResourceId": {"Fn::GetAtt": ["API", "RootResourceId"]},
          "Stage": {"Ref": "Stage"},
          "ApiDeploymentId": {"Ref": "Deployment"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "QnABotCommonLambdaLayer": {"Ref": "QnABotCommonLambdaLayer"},
          "LexVersion": "V2",
          "LexV2BotName": {"Fn::GetAtt": ["LexV2Bot", "botName"]},
          "LexV2BotId": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
          "LexV2BotAlias": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]},
          "LexV2BotAliasId": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
          "LexV2BotLocaleIds": {"Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]},
          "KendraFaqIndexId": {"Ref": "KendraFaqIndexId"},
          "KendraWebPageIndexId": {"Ref": "KendraWebPageIndexId"},
          "LogRetentionPeriod": {"Ref": "LogRetentionPeriod"}
        }
      }
    },
    "ImportStack": {
      "Type": "AWS::CloudFormation::Stack",
      "DependsOn": ["PreUpgradeExport"],
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v7.3.14/templates/import.json"
        },
        "Parameters": {
          "ContentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "S3Clean": {"Fn::GetAtt": ["S3Clean", "Arn"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v7.3.14",
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsArn": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "ImportBucket": {"Ref": "ImportBucket"},
          "ExportBucket": {"Ref": "ExportBucket"},
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "MetricsIndex": {"Fn::GetAtt": ["Var", "MetricsIndex"]},
          "FeedbackIndex": {"Fn::GetAtt": ["Var", "FeedbackIndex"]},
          "VPCSubnetIdList": {"Fn::Join": [",", {"Ref": "VPCSubnetIdList"}]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", {"Ref": "VPCSecurityGroupIdList"}]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "CommonModulesLambdaLayer": {"Ref": "CommonModulesLambdaLayer"},
          "EsProxyLambdaLayer": {"Ref": "EsProxyLambdaLayer"},
          "QnABotCommonLambdaLayer": {"Ref": "QnABotCommonLambdaLayer"},
          "EmbeddingsLambdaArn": {"Ref": "EmbeddingsLambdaArn"},
          "EmbeddingsApi": {"Ref": "EmbeddingsApi"},
          "EmbeddingsLambdaDimensions": {"Ref": "EmbeddingsLambdaDimensions"},
          "EmbeddingsBedrockModelId": {"Ref": "EmbeddingsBedrockModelId"},
          "LogRetentionPeriod": {"Ref": "LogRetentionPeriod"},
          "SettingsTable": {"Ref": "SettingsTable"}
        }
      }
    },
    "CommonModulesLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {
          "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/common-modules-layer.zip"
        },
        "BuildDate": "2026-06-09T15:56:38.740Z"
      }
    },
    "CommonModulesLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "CommonModules",
              {
                "Fn::Select": [
                  "0",
                  {"Fn::Split": ["-", {"Ref": "AWS::StackName"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/common-modules-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "CommonModulesLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs24.x"]
      }
    },
    "QnABotCommonLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {
          "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/qnabot-common-layer.zip"
        },
        "BuildDate": "2026-06-09T15:56:38.740Z"
      }
    },
    "QnABotCommonLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "QnABotCommon",
              {
                "Fn::Select": [
                  "0",
                  {"Fn::Split": ["-", {"Ref": "AWS::StackName"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/qnabot-common-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "QnABotCommonLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs24.x"]
      }
    },
    "AwsSdkLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/aws-sdk-layer.zip"},
        "BuildDate": "2026-06-09T15:56:38.740Z"
      }
    },
    "AwsSdkLayerLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/aws-sdk-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "AwsSdkLayerCodeVersion"}
        },
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "AwsSdk",
              {
                "Fn::Select": [
                  "0",
                  {"Fn::Split": ["-", {"Ref": "AWS::StackName"}]}
                ]
              }
            ]
          ]
        },
        "CompatibleRuntimes": ["nodejs24.x"]
      }
    },
    "CfnLambdaLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/cfn-lambda-layer.zip"},
        "BuildDate": "2026-06-09T15:56:38.740Z"
      }
    },
    "CfnLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "CfnLambdaModule",
              {
                "Fn::Select": [
                  "0",
                  {"Fn::Split": ["-", {"Ref": "AWS::StackName"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/cfn-lambda-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "CfnLambdaLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs24.x"]
      }
    },
    "EsProxyLayerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/es-proxy-layer.zip"},
        "BuildDate": "2026-06-09T15:56:38.740Z"
      }
    },
    "EsProxyLambdaLayer": {
      "Type": "AWS::Lambda::LayerVersion",
      "Properties": {
        "LayerName": {
          "Fn::Join": [
            "-",
            [
              "EsProxy",
              {
                "Fn::Select": [
                  "0",
                  {"Fn::Split": ["-", {"Ref": "AWS::StackName"}]}
                ]
              }
            ]
          ]
        },
        "Content": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/es-proxy-layer.zip"
          },
          "S3ObjectVersion": {"Ref": "EsProxyLayerCodeVersion"}
        },
        "CompatibleRuntimes": ["nodejs24.x"]
      }
    },
    "QNAInvokePermission": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": "FulfillmentLambdaAliaslive",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::Join": [
            ":",
            [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
          ]
        },
        "Principal": "lex.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "LexV2Bot": {
      "Type": "Custom::LexV2Bot",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]},
        "description": "QnABot LexV2 Bot7.3.14 - v1",
        "BuildDate": "2026-06-09T15:56:38.740Z",
        "localIds": {"Ref": "LexV2BotLocaleIds"},
        "utterances": ["dummy utterance"]
      }
    },
    "Alexa": {
      "Type": "AWS::Lambda::Permission",
      "DependsOn": "FulfillmentLambdaAliaslive",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {
          "Fn::Join": [
            ":",
            [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
          ]
        },
        "Principal": "alexa-appkit.amazon.com"
      }
    },
    "FulfillmentCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/fulfillment.zip"},
        "BuildDate": "2026-06-09T15:56:38.755Z"
      }
    },
    "FulfillmentLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-FulfillmentLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "FulfillmentLambda": {
      "Type": "AWS::Lambda::Function",
      "DependsOn": "FulfillmentCodeVersion",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/fulfillment.zip"},
          "S3ObjectVersion": {"Ref": "FulfillmentCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "Fn::If": [
              "BuildExamples",
              {
                "ES_TYPE": {"Fn::GetAtt": ["Var", "QnAType"]},
                "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
                "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
                "LAMBDA_DEFAULT_QUERY": {"Ref": "ESQueryLambda"},
                "LAMBDA_LOG": {"Ref": "ESLoggingLambda"},
                "ES_SERVICE_QID": {"Ref": "ESQidLambda"},
                "ES_SERVICE_PROXY": {"Ref": "ESProxyLambda"},
                "DYNAMODB_USERSTABLE": {"Ref": "UsersTable"},
                "DEFAULT_USER_POOL_JWKS_PARAM": {
                  "Ref": "DefaultUserPoolJwksUrl"
                },
                "SETTINGS_TABLE": {"Ref": "SettingsTable"},
                "EMBEDDINGS_API": {"Ref": "EmbeddingsApi"},
                "EMBEDDINGS_LAMBDA_ARN": {"Ref": "EmbeddingsLambdaArn"},
                "LLM_API": {"Ref": "LLMApi"},
                "LLM_LAMBDA_ARN": {"Ref": "LLMLambdaArn"},
                "AWS_ACCOUNT_ID": {"Ref": "AWS::AccountId"},
                "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
                "ExampleJSLambdaQuiz": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
                },
                "ExampleJSLambdahook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
                },
                "ExamplePYTHONLambdaBotBroker": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaBotBroker"
                  ]
                },
                "ExamplePYTHONLambdaConnectCallback": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaConnectCallback"
                  ]
                },
                "ExamplePYTHONLambdaFeedback": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaFeedback"
                  ]
                },
                "ExamplePYTHONLambdaNext": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaNext"
                  ]
                },
                "ExamplePYTHONLambdaPrevious": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaPrevious"
                  ]
                },
                "ExamplePYTHONLambdahello": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdahello"
                  ]
                },
                "EXTCreateRecentTopicsResponse": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.EXTCreateRecentTopicsResponse"
                  ]
                },
                "EXTCustomJSHook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
                },
                "EXTCustomPYHook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]
                },
                "QNAWage": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAWage"]},
                "QNASocialSecurity": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNASocialSecurity"]
                },
                "QNAPinNoConfirm": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPinNoConfirm"]
                },
                "QNAPin": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPin"]},
                "QNAYesNo": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAYesNo"]
                },
                "QNAYesNoExit": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAYesNoExit"]
                },
                "QNADate": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNADate"]},
                "QNADateNoConfirm": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNADateNoConfirm"]
                },
                "QNADayOfWeek": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNADayOfWeek"]
                },
                "QNAMonth": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAMonth"]
                },
                "QNAMonthNoConfirm": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAMonthNoConfirm"]
                },
                "QNANumber": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNANumber"]
                },
                "QNANumberNoConfirm": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNANumberNoConfirm"]
                },
                "QNAAge": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAAge"]},
                "QNAAgeNoConfirm": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAAgeNoConfirm"]
                },
                "QNAPhoneNumber": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAPhoneNumber"]
                },
                "QNAPhoneNumberNoConfirm": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.QNAPhoneNumberNoConfirm"
                  ]
                },
                "QNATime": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNATime"]},
                "QNAEmailAddress": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.QNAEmailAddress"]
                },
                "QNAName": {"Fn::GetAtt": ["ExamplesStack", "Outputs.QNAName"]},
                "SOLUTION_ID": "SO0189",
                "SOLUTION_VERSION": "v7.3.14"
              },
              {
                "ES_TYPE": {"Fn::GetAtt": ["Var", "QnAType"]},
                "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
                "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
                "LAMBDA_DEFAULT_QUERY": {"Ref": "ESQueryLambda"},
                "LAMBDA_LOG": {"Ref": "ESLoggingLambda"},
                "ES_SERVICE_QID": {"Ref": "ESQidLambda"},
                "ES_SERVICE_PROXY": {"Ref": "ESProxyLambda"},
                "DYNAMODB_USERSTABLE": {"Ref": "UsersTable"},
                "DEFAULT_USER_POOL_JWKS_PARAM": {
                  "Ref": "DefaultUserPoolJwksUrl"
                },
                "SETTINGS_TABLE": {"Ref": "SettingsTable"},
                "EMBEDDINGS_API": {"Ref": "EmbeddingsApi"},
                "EMBEDDINGS_LAMBDA_ARN": {"Ref": "EmbeddingsLambdaArn"},
                "LLM_API": {"Ref": "LLMApi"},
                "LLM_LAMBDA_ARN": {"Ref": "LLMLambdaArn"},
                "AWS_ACCOUNT_ID": {"Ref": "AWS::AccountId"},
                "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
                "SOLUTION_ID": "SO0189",
                "SOLUTION_VERSION": "v7.3.14"
              }
            ]
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "FulfillmentLambdaLogGroup"}},
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "MemorySize": 1408,
        "Role": {"Fn::GetAtt": ["FulfillmentLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "TracingConfig": {
          "Mode": {"Fn::If": ["XRAYEnabled", "Active", "PassThrough"]}
        },
        "Tags": [{"Key": "Type", "Value": "Fulfillment"}],
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W89",
              "reason": "This Lambda Function is not required to be inside VPC"
            },
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "FulfillmentLambdaVersionGenerator": {
      "Type": "Custom::LambdaVersion",
      "DeletionPolicy": "Retain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "FunctionName": {"Ref": "FulfillmentLambda"},
        "Triggers": {
          "FulfillmentCodeVersionTrigger": [{"Ref": "FulfillmentCodeVersion"}],
          "LayersTrigger": [
            {"Ref": "AwsSdkLayerLambdaLayer"},
            {"Ref": "CommonModulesLambdaLayer"},
            {"Ref": "EsProxyLambdaLayer"},
            {"Ref": "QnABotCommonLambdaLayer"}
          ],
          "EmbeddingsTrigger": [
            {"Ref": "EmbeddingsApi"},
            {"Ref": "EmbeddingsLambdaArn"}
          ],
          "QASummarizeTrigger": [{"Ref": "LLMApi"}, {"Ref": "LLMLambdaArn"}]
        }
      }
    },
    "FulfillmentLambdaAliaslive": {
      "Type": "AWS::Lambda::Alias",
      "DependsOn": "FulfillmentLambdaVersionGenerator",
      "Properties": {
        "FunctionName": {"Ref": "FulfillmentLambda"},
        "FunctionVersion": {
          "Fn::GetAtt": ["FulfillmentLambdaVersionGenerator", "Version"]
        },
        "Name": "live",
        "ProvisionedConcurrencyConfig": {
          "Fn::If": [
            "CreateConcurrency",
            {
              "ProvisionedConcurrentExecutions": {
                "Ref": "FulfillmentConcurrency"
              }
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      }
    },
    "InvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Fn::If": [
            "BuildExamples",
            {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    "arn:aws:lambda:*:*:function:qna-*",
                    "arn:aws:lambda:*:*:function:QNA-*",
                    {"Fn::GetAtt": ["ESQueryLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESLoggingLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
                    {
                      "Fn::If": [
                        "EmbeddingsLambdaArn",
                        {"Ref": "EmbeddingsLambdaArn"},
                        {"Ref": "AWS::NoValue"}
                      ]
                    },
                    {
                      "Fn::If": [
                        "LLMLambdaArn",
                        {"Ref": "LLMLambdaArn"},
                        {"Ref": "AWS::NoValue"}
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExampleJSLambdaQuiz"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExampleJSLambdahook"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaBotBroker"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaConnectCallback"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaFeedback"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaNext"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaPrevious"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdahello"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.EXTCreateRecentTopicsResponse"
                      ]
                    },
                    {
                      "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
                    },
                    {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]}
                  ]
                }
              ]
            },
            {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    "arn:aws:lambda:*:*:function:qna-*",
                    "arn:aws:lambda:*:*:function:QNA-*",
                    {"Fn::GetAtt": ["ESQueryLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESLoggingLambda", "Arn"]},
                    {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
                    {
                      "Fn::If": [
                        "EmbeddingsLambdaArn",
                        {"Ref": "EmbeddingsLambdaArn"},
                        {"Ref": "AWS::NoValue"}
                      ]
                    },
                    {
                      "Fn::If": [
                        "LLMLambdaArn",
                        {"Ref": "LLMLambdaArn"},
                        {"Ref": "AWS::NoValue"}
                      ]
                    }
                  ]
                }
              ]
            }
          ]
        },
        "Roles": [{"Ref": "FulfillmentLambdaRole"}]
      }
    },
    "LexBotPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lex:RecognizeText"],
              "Resource": ["arn:aws:lex:*:*:bot:QNA*", "arn:aws:lex:*:*:bot*"]
            }
          ]
        },
        "Roles": [{"Ref": "FulfillmentLambdaRole"}]
      },
      "Metadata": {
        "guard": {"SuppressedRules": ["IAM_POLICY_NON_COMPLIANT_ARN"]}
      }
    },
    "BedrockInvokeModelAccessPolicyResources": {
      "Type": "Custom::ModelAccess",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "EmbeddingsBedrockModelId": {
          "Fn::If": [
            "EmbeddingsBedrock",
            {
              "Fn::FindInMap": [
                "BedrockDefaults",
                {"Ref": "EmbeddingsBedrockModelId"},
                "ModelID"
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "LLMBedrockModelId": {
          "Fn::If": [
            "LLMBedrock",
            {"Ref": "LLMBedrockModelId"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "BedrockKnowledgeBaseModelId": {
          "Fn::If": [
            "BedrockKnowledgeBaseEnable",
            {"Ref": "BedrockKnowledgeBaseModel"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      }
    },
    "FulfillmentLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Action": [
                    "translate:TranslateText",
                    "translate:GetTerminology",
                    "translate:ListTerminologies",
                    "comprehend:DetectDominantLanguage",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:ListMetrics"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "translateReadOnly"
          },
          {
            "PolicyName": "AWSQnaBotComprehendReadOnly",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "comprehend:DetectDominantLanguage",
                    "comprehend:DetectEntities",
                    "comprehend:DetectKeyPhrases",
                    "comprehend:DetectPiiEntities",
                    "comprehend:ContainsPiiEntities",
                    "comprehend:DetectSentiment",
                    "comprehend:DetectSyntax",
                    "comprehend:DescribeEntityRecognizer",
                    "comprehend:ListEntityRecognizers"
                  ],
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "Fn::If": [
              "StreamingEnabled",
              {
                "PolicyName": "StreamingPermissions",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": [
                        "execute-api:Invoke",
                        "execute-api:ManageConnections"
                      ],
                      "Resource": [
                        {
                          "Fn::Join": [
                            "",
                            [
                              "arn:",
                              {"Fn::Sub": "${AWS::Partition}"},
                              ":execute-api:",
                              {"Fn::Sub": "${AWS::Region}"},
                              ":",
                              {"Fn::Sub": "${AWS::AccountId}"},
                              ":",
                              {
                                "Fn::GetAtt": [
                                  "StreamingStack",
                                  "Outputs.StreamingWebSocketApiId"
                                ]
                              },
                              "/Prod/*"
                            ]
                          ]
                        }
                      ]
                    },
                    {
                      "Effect": "Allow",
                      "Action": ["dynamodb:GetItem"],
                      "Resource": [
                        {
                          "Fn::GetAtt": [
                            "StreamingStack",
                            "Outputs.StreamingDynamoDbTableArn"
                          ]
                        }
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "DefaultUserPoolJwksUrl"}
                        ]
                      ]
                    }
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "DynamoDBPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["dynamodb:GetItem", "dynamodb:PutItem"],
                  "Resource": [
                    {"Fn::GetAtt": ["UsersTable", "Arn"]},
                    {"Fn::GetAtt": ["SettingsTable", "Arn"]}
                  ]
                }
              ]
            }
          },
          {
            "Fn::If": [
              "BedrockEnable",
              {
                "PolicyName": "BedrockInvokeModelAccess",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": [
                        "bedrock:InvokeModel",
                        "bedrock:InvokeModelWithResponseStream"
                      ],
                      "Resource": {
                        "Fn::GetAtt": [
                          "BedrockInvokeModelAccessPolicyResources",
                          "modelArn"
                        ]
                      }
                    },
                    {
                      "Sid": "ApplyGuardrailsToLLMBedrock",
                      "Effect": "Allow",
                      "Action": ["bedrock:ApplyGuardrail"],
                      "Resource": [
                        {
                          "Fn::Sub": "arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:guardrail/*"
                        }
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "Fn::If": [
              "BedrockKnowledgeBaseEnable",
              {
                "PolicyName": "BedrockKnowledgeBaseAccess",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": [
                        "bedrock:Retrieve",
                        "bedrock:RetrieveAndGenerate"
                      ],
                      "Resource": {
                        "Fn::Sub": "arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/${BedrockKnowledgeBaseId}"
                      }
                    },
                    {
                      "Sid": "ApplyGuardrailsToKnowledgeBase",
                      "Effect": "Allow",
                      "Action": ["bedrock:ApplyGuardrail"],
                      "Resource": [
                        {
                          "Fn::Sub": "arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:guardrail/*"
                        }
                      ]
                    },
                    {
                      "Sid": "GetInferenceProfileForKnowledgeBase",
                      "Effect": "Allow",
                      "Action": ["bedrock:GetInferenceProfile"],
                      "Resource": [
                        {
                          "Fn::Sub": "arn:${AWS::Partition}:bedrock:${AWS::Region}:${AWS::AccountId}:inference-profile/*"
                        }
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "PolicyName": "S3QNABucketReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": ["arn:aws:s3:::QNA*/*", "arn:aws:s3:::qna*/*"]
                }
              ]
            }
          },
          {
            "PolicyName": "SettingsTableReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["dynamodb:Scan"],
                  "Resource": [{"Fn::GetAtt": ["SettingsTable", "Arn"]}]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "ESWarmerCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/warmer.zip"},
        "BuildDate": "2026-06-09T15:56:38.755Z"
      }
    },
    "ESWarmerLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESWarmerLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESWarmerLambda": {
      "DependsOn": ["ESWarmerCodeVersion"],
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/warmer.zip"},
          "S3ObjectVersion": {"Ref": "ESWarmerCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "REPEAT_COUNT": "4",
            "TARGET_PATH": "_search",
            "TARGET_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "TARGET_URL": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "SETTINGS_TABLE": {"Ref": "SettingsTable"},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.warmer",
        "LoggingConfig": {"LogGroup": {"Ref": "ESWarmerLambdaLogGroup"}},
        "MemorySize": "512",
        "Role": {"Fn::GetAtt": ["WarmerLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Warmer"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "WarmerLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "AllowES",
                  "Effect": "Allow",
                  "Action": ["es:ESHttpGet"],
                  "Resource": ["*"]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "ESWarmerRule": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "ScheduleExpression": "rate(1 minute)",
        "Targets": [
          {
            "Id": "ESWarmerScheduler",
            "Arn": {"Fn::GetAtt": ["ESWarmerLambda", "Arn"]}
          }
        ]
      }
    },
    "ESWarmerRuleInvokeLambdaPermission": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {"Fn::GetAtt": ["ESWarmerLambda", "Arn"]},
        "Action": "lambda:InvokeFunction",
        "Principal": "events.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["ESWarmerRule", "Arn"]}
      }
    },
    "LexBuildLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexBuildLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "LexBuildLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/lex-build.zip"},
          "S3ObjectVersion": {"Ref": "LexBuildCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "UTTERANCE_BUCKET": {"Ref": "AssetBucket"},
            "UTTERANCE_KEY": "default-utterances.json",
            "POLL_LAMBDA": {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "LEXV2_BUILD_LAMBDA": {"Ref": "Lexv2BotLambda"},
            "ADDRESS": {
              "Fn::Join": [
                "",
                ["https://", {"Fn::GetAtt": ["ESVar", "ESAddress"]}]
              ]
            },
            "INDEX": {"Fn::GetAtt": ["Var", "index"]},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexBuildLambdaLogGroup"}},
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"}
        ],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "LexBuildLambdaStartLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexBuildLambdaStart"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "LexBuildLambdaStart": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda');\nconst { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\n\nconst region = process.env.AWS_REGION;\nconst lambda = new LambdaClient(customSdkConfig('C002', { region }));\nconst s3 = new S3Client(customSdkConfig('C022', { region }));\nconst crypto = require('crypto');\n\nexports.handler = async function (event, context) {\n    const token = crypto.randomBytes(16).toString('base64');\n    const bucket = process.env.STATUS_BUCKET;\n    const lexV2StatusFile = process.env.LEXV2_STATUS_KEY;\n    const functionName = process.env.BUILD_FUNCTION;\n    const body = JSON.stringify({ status: 'Starting', token });\n\n    console.log('Initializing ', bucket, lexV2StatusFile);\n    const params = {\n        Bucket: bucket,\n        Key: lexV2StatusFile,\n        Body: body,\n    };\n    const putObjectCmdV2 = new PutObjectCommand(params);\n    await s3.send(putObjectCmdV2);\n\n    // The BUILD_FUNCTION takes care of rebuilding Lex V2 bot\n    console.log('Invoking ', functionName);\n    const invokeParams = {\n        FunctionName: functionName,\n        InvocationType: 'Event',\n        Payload: '{}',\n    };\n    const invokeCmd = new InvokeCommand(invokeParams);\n    await lambda.send(invokeCmd);\n    return { token };\n};\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "BUILD_FUNCTION": {"Fn::GetAtt": ["LexBuildLambda", "Arn"]},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexBuildLambdaStartLogGroup"}},
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"}
        ],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "LexBuildLambdaPollLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexBuildLambdaPoll"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "LexBuildLambdaPoll": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { LambdaClient, InvokeCommand } = require('@aws-sdk/client-lambda');\nconst { LexModelBuildingServiceClient, GetBotCommand } = require('@aws-sdk/client-lex-model-building-service');\nconst { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\n\nconst region = process.env.AWS_REGION;\nconst lambda = new LambdaClient(customSdkConfig('C001', { region }));\nconst lex = new LexModelBuildingServiceClient(customSdkConfig('C001', { region }));\nconst s3 = new S3Client(customSdkConfig('C001', { region }));\n\nconst invokeLambda = async function invokeLambda(event) {\n    return new Promise((res, rej) => {\n        setTimeout(async () => {\n            const params = {\n                FunctionName: process.env.AWS_LAMBDA_FUNCTION_NAME,\n                InvocationType: 'Event',\n                Payload: JSON.stringify(event),\n            };\n            const invokeCmd = new InvokeCommand(params);\n            await lambda.send(invokeCmd)\n                .then((result) => {\n                    res(result);\n                })\n                .catch((e) => {\n                    console.log(e);\n                    rej(e);\n                });\n        }, 2000);\n    });\n};\n\nexports.handler = async function (event, context) {\n    try {\n        const getObjCmd = new GetObjectCommand({\n            Bucket: process.env.STATUS_BUCKET,\n            Key: process.env.STATUS_KEY,\n        });\n        const s3Response = await s3.send(getObjCmd);\n        const readableStream = Buffer.concat(await s3Response.Body.toArray());\n        const status = JSON.parse(readableStream);\n\n        const getBotCmd = new GetBotCommand({\n            name: process.env.BOT_NAME,\n            versionOrAlias: '$LATEST',\n        });\n        const lexResponse = await lex.send(getBotCmd);\n\n        status.status = lexResponse.status;\n\n        if (lexResponse.status === 'BUILDING') {\n            await invokeLambda(event);\n        }\n\n        const params = {\n            Bucket: process.env.STATUS_BUCKET,\n            Key: process.env.STATUS_KEY,\n            Body: JSON.stringify(status),\n        };\n        const putObjectCmd = new PutObjectCommand(params);\n        await s3.send(putObjectCmd);\n    } catch (error) {\n        console.log('An error occurred in master lex-build: ', error);\n        throw new Error(error.message);\n    }\n};\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexBuildLambdaPollLogGroup"}},
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["LexBuildLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"}
        ],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "LexBuildCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/lex-build.zip"},
        "BuildDate": "2026-06-09T15:56:38.756Z"
      }
    },
    "LexBuildInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lambda:InvokeFunction"],
              "Resource": [
                {"Fn::GetAtt": ["LexBuildLambda", "Arn"]},
                {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
                {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]}
              ]
            }
          ]
        },
        "Roles": [{"Ref": "LexBuildLambdaRole"}]
      }
    },
    "LexBuildLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "AssetBucketAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${AssetBucket}*"},
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:Put*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ],
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "BuildStatusBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "Properties": {
        "LifecycleConfiguration": {
          "Rules": [
            {"NoncurrentVersionExpirationInDays": 1, "Status": "Enabled"},
            {
              "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 1},
              "Status": "Enabled"
            }
          ]
        },
        "VersioningConfiguration": {"Status": "Enabled"},
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/BuildStatus/"]]
          }
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        }
      }
    },
    "HTTPSOnlyBuildStatusBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "BuildStatusBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["BuildStatusBucket", "Arn"]}, "/*"]
                  ]
                },
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["BuildStatusBucket", "Arn"]}]
                  ]
                }
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      },
      "Metadata": {
        "aws:cdk:path": "serverless-bot-framework/CloudfrontStaticWebsite/CloudFrontToS3/S3LoggingBucket/Policy/Resource"
      }
    },
    "BuildStatusClean": {
      "Type": "Custom::S3Clean",
      "DependsOn": ["CFNInvokePolicy", "HTTPSOnlyBuildStatusBucketPolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["S3Clean", "Arn"]},
        "Bucket": {"Ref": "BuildStatusBucket"}
      }
    },
    "LexV2BotLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexV2BotLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "Lexv2BotLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/lexv2-build.zip"},
          "S3ObjectVersion": {"Ref": "Lexv2BotCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "STACKNAME": {"Ref": "AWS::StackName"},
            "FULFILLMENT_LAMBDA_ARN": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "LOCALES": {"Ref": "LexV2BotLocaleIds"},
            "PYTHONPATH": "/var/task/py_modules:/var/runtime:/opt/python",
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "handler.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexV2BotLambdaLogGroup"}},
        "MemorySize": "1024",
        "Role": {"Fn::GetAtt": ["Lexv2BotLambdaRole", "Arn"]},
        "Runtime": "python3.14",
        "Timeout": 900,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "Lexv2BotCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/lexv2-build.zip"},
        "BuildDate": "2026-06-09T15:56:38.757Z"
      }
    },
    "Lexv2BotLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "LexV2ServiceLinkedRole",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole", "iam:DeleteRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringLike": {"iam:AWSServiceName": "lexv2.amazonaws.com"}
                  }
                },
                {
                  "Action": ["iam:PassRole"],
                  "Effect": "Allow",
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringLike": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Action": [
                    "translate:TranslateText",
                    "comprehend:DetectDominantLanguage"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            }
          },
          {
            "PolicyName": "BuildStatusBucketAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*", "s3:Put*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ],
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "OpensearchDomain": {
      "Type": "AWS::OpenSearchService::Domain",
      "DependsOn": ["PreUpgradeExport", "ESCognitoRole"],
      "Condition": "CreateDomain",
      "UpdatePolicy": {"EnableVersionUpgrade": true},
      "Metadata": {
        "checkov": {
          "skip": [
            {
              "id": "CKV_AWS_84",
              "comment": "Logging is enabled via custom resource - see source/templates/master/opensearch/updates.js"
            },
            {
              "id": "CKV_AWS_317",
              "comment": "Logging is enabled via custom resource - see source/templates/master/opensearch/updates.js"
            }
          ]
        }
      },
      "Properties": {
        "Fn::If": [
          "MasterNodesEnabled",
          {
            "CognitoOptions": {
              "Enabled": true,
              "IdentityPoolId": {"Ref": "OpenSearchDashboardsIdPool"},
              "RoleArn": {"Fn::GetAtt": ["ESCognitoRole", "Arn"]},
              "UserPoolId": {"Ref": "UserPool"}
            },
            "EBSOptions": {
              "EBSEnabled": true,
              "VolumeSize": {"Ref": "OpenSearchEBSVolumeSize"},
              "VolumeType": "gp3"
            },
            "EngineVersion": "OpenSearch_2.19",
            "SnapshotOptions": {"AutomatedSnapshotStartHour": "0"},
            "AdvancedOptions": {
              "rest.action.multi.allow_explicit_index": "true"
            },
            "EncryptionAtRestOptions": {"Enabled": true},
            "NodeToNodeEncryptionOptions": {"Enabled": true},
            "DomainEndpointOptions": {
              "EnforceHTTPS": true,
              "TLSSecurityPolicy": "Policy-Min-TLS-1-2-2019-07"
            },
            "VPCOptions": {
              "Fn::If": [
                "VPCEnabled",
                {
                  "SubnetIds": {"Ref": "VPCSubnetIdList"},
                  "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
                },
                {"Ref": "AWS::NoValue"}
              ]
            },
            "ClusterConfig": {
              "DedicatedMasterEnabled": "true",
              "DedicatedMasterType": {
                "Ref": "OpenSearchMasterNodeInstanceType"
              },
              "DedicatedMasterCount": {"Ref": "OpenSearchMasterNodeCount"},
              "InstanceCount": {"Ref": "OpenSearchNodeCount"},
              "InstanceType": {"Ref": "OpenSearchNodeInstanceType"},
              "ZoneAwarenessEnabled": {"Fn::If": ["SingleNode", false, true]}
            }
          },
          {
            "CognitoOptions": {
              "Enabled": true,
              "IdentityPoolId": {"Ref": "OpenSearchDashboardsIdPool"},
              "RoleArn": {"Fn::GetAtt": ["ESCognitoRole", "Arn"]},
              "UserPoolId": {"Ref": "UserPool"}
            },
            "EBSOptions": {
              "EBSEnabled": true,
              "VolumeSize": {"Ref": "OpenSearchEBSVolumeSize"},
              "VolumeType": "gp3"
            },
            "EngineVersion": "OpenSearch_2.19",
            "SnapshotOptions": {"AutomatedSnapshotStartHour": "0"},
            "AdvancedOptions": {
              "rest.action.multi.allow_explicit_index": "true"
            },
            "EncryptionAtRestOptions": {"Enabled": true},
            "NodeToNodeEncryptionOptions": {"Enabled": true},
            "DomainEndpointOptions": {
              "EnforceHTTPS": true,
              "TLSSecurityPolicy": "Policy-Min-TLS-1-2-2019-07"
            },
            "VPCOptions": {
              "Fn::If": [
                "VPCEnabled",
                {
                  "SubnetIds": {"Ref": "VPCSubnetIdList"},
                  "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
                },
                {"Ref": "AWS::NoValue"}
              ]
            },
            "ClusterConfig": {
              "DedicatedMasterEnabled": "false",
              "InstanceCount": {"Ref": "OpenSearchNodeCount"},
              "InstanceType": {"Ref": "OpenSearchNodeInstanceType"},
              "ZoneAwarenessEnabled": {"Fn::If": ["SingleNode", false, true]}
            }
          }
        ]
      }
    },
    "ESCognitoRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "opensearchservice.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "AWSQnaBotESCognitoAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-idp:DescribeUserPool",
                    "cognito-idp:CreateUserPoolClient",
                    "cognito-idp:DeleteUserPoolClient",
                    "cognito-idp:DescribeUserPoolClient",
                    "cognito-idp:AdminInitiateAuth",
                    "cognito-idp:AdminUserGlobalSignOut",
                    "cognito-idp:ListUserPoolClients"
                  ],
                  "Resource": [{"Fn::GetAtt": ["UserPool", "Arn"]}]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-identity:DescribeIdentityPool",
                    "cognito-identity:UpdateIdentityPool",
                    "cognito-identity:GetIdentityPoolRoles"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cognito-identity:${AWS::Region}:${AWS::AccountId}:identitypool/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["cognito-identity:SetIdentityPoolRoles"],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "iam:PassRole",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/${AWS::StackName}-*"
                    }
                  ],
                  "Condition": {
                    "StringLike": {
                      "iam:PassedToService": "cognito-identity.amazonaws.com"
                    }
                  }
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {
              "id": "F38",
              "reason": "This role policy is required to have * action in its policy with PassRole action"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "ESInfo": {
      "Type": "Custom::ESProxy",
      "Condition": "DontCreateDomain",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
        "name": "EMPTY"
      }
    },
    "ESInfoLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Condition": "DontCreateDomain",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESInfoLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESInfoLambda": {
      "Type": "AWS::Lambda::Function",
      "Condition": "DontCreateDomain",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { OpenSearchClient, DescribeDomainCommand } = require('@aws-sdk/client-opensearch');\n\nconst region = process.env.AWS_REGION;\nconst client = new OpenSearchClient({\n    customUserAgent: [\n        [`AWSSOLUTION/${process.env.SOLUTION_ID}/${process.env.SOLUTION_VERSION}`],\n        [`AWSSOLUTION-CAPABILITY/${process.env.SOLUTION_ID}-C023/${process.env.SOLUTION_VERSION}`]\n    ],\n    region,\n});\n\nconst SUCCESS = 'SUCCESS';\nconst FAILED = 'FAILED';\nconst https = require('https');\nconst { URL } = require('url');\n\nasync function send(event, context, responseStatus, responseData, physicalResourceId, noEcho) {\n    return new Promise((resolve, reject) => {\n        const responseBody = JSON.stringify({\n            Status: responseStatus,\n            Reason: `See the details in CloudWatch Log Stream: ${context.logStreamName}`,\n            PhysicalResourceId: physicalResourceId || context.logStreamName,\n            StackId: event.StackId,\n            RequestId: event.RequestId,\n            LogicalResourceId: event.LogicalResourceId,\n            NoEcho: noEcho || false,\n            Data: responseData,\n        });\n\n        console.log('Response body:\\n', responseBody);\n\n        const parsedUrl = new URL(event.ResponseURL);\n\n        const options = {\n            hostname: parsedUrl.hostname,\n            port: 443,\n            path: parsedUrl.pathname + parsedUrl.search,\n            method: 'PUT',\n            headers: {\n                'content-type': '',\n                'content-length': responseBody.length,\n            },\n        };\n\n        const request = https.request(options, (response) => {\n            console.log(`Status code: ${response.statusCode}`);\n            console.log(`Status message: ${response.statusMessage}`);\n            response.on('end', () => {\n                resolve();\n            });\n        });\n\n        request.on('error', (error) => {\n            console.log(`send(..) failed executing https.request(..): ${error}`);\n            reject(error);\n        });\n\n        request.write(responseBody);\n        request.end();\n    });\n}\n\nexports.handler = async function (event, context) {\n    console.log(JSON.stringify(event, null, 2));\n\n    if (event.RequestType !== 'Delete') {\n        const describeDomainCmd = new DescribeDomainCommand({\n            DomainName: event.ResourceProperties.name,\n        });\n        try {\n            const info = await client.send(describeDomainCmd);\n            await send(event, context, SUCCESS, {\n                Name: info.DomainStatus.DomainName,\n                Arn: info.DomainStatus.ARN,\n                Endpoint: info.DomainStatus.Endpoints,\n            });\n        } catch (e) {\n            console.log(e);\n            await send(event, context, FAILED);\n        }\n    } else {\n        await send(event, context, SUCCESS);\n    }\n    context.done();\n};\n"
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "ESInfoLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "FeedbackKinesisFirehoseLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {
                "Fn::Sub": "/aws/kinesisfirehose/${AWS::StackName}-FeedbackKinesisFirehose"
              },
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {"id": "W86", "reason": "LogGroup is encrypted by default."}
          ]
        },
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "FeedbackKinesisFirehoseStreamOpenSearch": {
      "Type": "AWS::Logs::LogStream",
      "DependsOn": ["FeedbackKinesisFirehoseLogGroup"],
      "Properties": {
        "LogGroupName": {"Ref": "FeedbackKinesisFirehoseLogGroup"},
        "LogStreamName": "OpenSearchDestinationDelivery"
      }
    },
    "FeedbackKinesisFirehoseStreamS3": {
      "Type": "AWS::Logs::LogStream",
      "DependsOn": ["FeedbackKinesisFirehoseLogGroup"],
      "Properties": {
        "LogGroupName": {"Ref": "FeedbackKinesisFirehoseLogGroup"},
        "LogStreamName": "S3BackupDelivery"
      }
    },
    "FeedbackKinesisFirehose": {
      "Type": "AWS::KinesisFirehose::DeliveryStream",
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "KINESIS_FIREHOSE_SPLUNK_DESTINATION_CONFIGURATION_NO_PLAINTEXT_PASSWORD",
            "KINESIS_FIREHOSE_REDSHIFT_DESTINATION_CONFIGURATION_NO_PLAINTEXT_PASSWORD"
          ]
        }
      },
      "DependsOn": [
        "FeedbackKinesisFirehoseStreamS3",
        "FeedbackKinesisFirehoseStreamOpenSearch",
        "FirehoseESS3Role"
      ],
      "Properties": {
        "DeliveryStreamType": "DirectPut",
        "DeliveryStreamEncryptionConfigurationInput": {
          "KeyType": "AWS_OWNED_CMK"
        },
        "AmazonopensearchserviceDestinationConfiguration": {
          "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
          "CloudWatchLoggingOptions": {
            "Enabled": true,
            "LogGroupName": {"Ref": "FeedbackKinesisFirehoseLogGroup"},
            "LogStreamName": {"Ref": "FeedbackKinesisFirehoseStreamOpenSearch"}
          },
          "DomainARN": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "IndexName": {"Fn::Sub": "${Var.FeedbackIndex}"},
          "IndexRotationPeriod": "NoRotation",
          "RetryOptions": {"DurationInSeconds": 300},
          "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
          "S3BackupMode": "AllDocuments",
          "S3Configuration": {
            "BucketARN": {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
            "CloudWatchLoggingOptions": {
              "Enabled": true,
              "LogGroupName": {"Ref": "FeedbackKinesisFirehoseLogGroup"},
              "LogStreamName": {"Ref": "FeedbackKinesisFirehoseStreamS3"}
            },
            "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
            "Prefix": "feedback/",
            "CompressionFormat": "UNCOMPRESSED",
            "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]}
          },
          "TypeName": "",
          "VpcConfiguration": {
            "Fn::If": [
              "VPCEnabled",
              {
                "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
                "SubnetIds": {"Ref": "VPCSubnetIdList"},
                "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
              },
              {"Ref": "AWS::NoValue"}
            ]
          }
        }
      }
    },
    "GeneralKinesisFirehoseLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {
                "Fn::Sub": "/aws/kinesisfirehose/${AWS::StackName}-GeneralKinesisFirehose"
              },
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {"id": "W86", "reason": "LogGroup is encrypted by default."}
          ]
        },
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "GeneralKinesisFirehoseStreamOpenSearch": {
      "Type": "AWS::Logs::LogStream",
      "Properties": {
        "LogGroupName": {"Ref": "GeneralKinesisFirehoseLogGroup"},
        "LogStreamName": "OpenSearchDestinationDelivery"
      }
    },
    "GeneralKinesisFirehoseStreamS3": {
      "Type": "AWS::Logs::LogStream",
      "Properties": {
        "LogGroupName": {"Ref": "GeneralKinesisFirehoseLogGroup"},
        "LogStreamName": "S3BackupDelivery"
      }
    },
    "GeneralKinesisFirehose": {
      "Type": "AWS::KinesisFirehose::DeliveryStream",
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "KINESIS_FIREHOSE_REDSHIFT_DESTINATION_CONFIGURATION_NO_PLAINTEXT_PASSWORD",
            "KINESIS_FIREHOSE_SPLUNK_DESTINATION_CONFIGURATION_NO_PLAINTEXT_PASSWORD"
          ]
        }
      },
      "DependsOn": [
        "GeneralKinesisFirehoseStreamOpenSearch",
        "GeneralKinesisFirehoseStreamS3",
        "FirehoseESS3Role"
      ],
      "Properties": {
        "DeliveryStreamType": "DirectPut",
        "DeliveryStreamEncryptionConfigurationInput": {
          "KeyType": "AWS_OWNED_CMK"
        },
        "AmazonopensearchserviceDestinationConfiguration": {
          "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
          "CloudWatchLoggingOptions": {
            "Enabled": true,
            "LogGroupName": {"Ref": "GeneralKinesisFirehoseLogGroup"},
            "LogStreamName": {"Ref": "GeneralKinesisFirehoseStreamOpenSearch"}
          },
          "DomainARN": {"Fn::GetAtt": ["ESVar", "ESArn"]},
          "IndexName": {"Fn::Sub": "${Var.MetricsIndex}"},
          "IndexRotationPeriod": "NoRotation",
          "RetryOptions": {"DurationInSeconds": 300},
          "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
          "S3BackupMode": "AllDocuments",
          "S3Configuration": {
            "BucketARN": {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
            "CloudWatchLoggingOptions": {
              "Enabled": true,
              "LogGroupName": {"Ref": "GeneralKinesisFirehoseLogGroup"},
              "LogStreamName": {"Ref": "GeneralKinesisFirehoseStreamS3"}
            },
            "Prefix": "metrics/",
            "BufferingHints": {"IntervalInSeconds": 60, "SizeInMBs": 5},
            "CompressionFormat": "UNCOMPRESSED",
            "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]}
          },
          "TypeName": "",
          "VpcConfiguration": {
            "Fn::If": [
              "VPCEnabled",
              {
                "RoleARN": {"Fn::GetAtt": ["FirehoseESS3Role", "Arn"]},
                "SubnetIds": {"Ref": "VPCSubnetIdList"},
                "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
              },
              {"Ref": "AWS::NoValue"}
            ]
          }
        }
      }
    },
    "MetricsBucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "DeletionPolicy": "Delete",
      "Properties": {
        "VersioningConfiguration": {"Status": "Enabled"},
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/Metrics/"]]
          }
        },
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "Tags": [{"Key": "Use", "Value": "Metrics"}]
      }
    },
    "HTTPSOnlyMetricBucketsPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "MetricsBucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {
                  "Fn::Join": [
                    "",
                    [{"Fn::GetAtt": ["MetricsBucket", "Arn"]}, "/*"]
                  ]
                },
                {"Fn::Join": ["", [{"Fn::GetAtt": ["MetricsBucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "MetricsBucketClean": {
      "Type": "Custom::S3Clean",
      "DependsOn": ["CFNInvokePolicy", "HTTPSOnlyMetricBucketsPolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["S3Clean", "Arn"]},
        "Bucket": {"Ref": "MetricsBucket"}
      }
    },
    "FirehoseESS3Role": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "firehose.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "FirehoseS3DeliveryPermissions",
                  "Effect": "Allow",
                  "Action": [
                    "s3:AbortMultipartUpload",
                    "s3:GetBucketLocation",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:ListBucketMultipartUploads",
                    "s3:PutObject"
                  ],
                  "Resource": [
                    {"Fn::GetAtt": ["MetricsBucket", "Arn"]},
                    {
                      "Fn::Join": [
                        "",
                        [{"Fn::GetAtt": ["MetricsBucket", "Arn"]}, "/*"]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "FirehoseLambdaPermissions",
                  "Effect": "Allow",
                  "Action": [
                    "lambda:InvokeFunction",
                    "lambda:GetFunctionConfiguration"
                  ],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:%FIREHOSE_DEFAULT_FUNCTION%:%FIREHOSE_DEFAULT_VERSION%"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "FirehoseOpenSearchDestinationPermissions",
                  "Effect": "Allow",
                  "Action": [
                    "es:DescribeDomain",
                    "es:DescribeDomains",
                    "es:DescribeDomainConfig",
                    "es:ESHttpPost",
                    "es:ESHttpPut",
                    "es:ESHttpGet"
                  ],
                  "Resource": [
                    {"Fn::GetAtt": ["ESVar", "ESArn"]},
                    {
                      "Fn::Join": [
                        "",
                        [{"Fn::GetAtt": ["ESVar", "ESArn"]}, "/*"]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "FirehoseLogsPermissions",
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:logs:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":log-group:/aws/kinesisfirehose/*"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Sid": "FireHoseVPCConfiguration",
                  "Effect": "Allow",
                  "Action": [
                    "ec2:DescribeVpcs",
                    "ec2:DescribeVpcAttribute",
                    "ec2:DescribeSubnets",
                    "ec2:DescribeSecurityGroups",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:CreateNetworkInterface",
                    "ec2:CreateNetworkInterfacePermission",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "QnAFirehose"
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "ESCFNProxyLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESCFNProxyLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESCFNProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "SETTINGS_TABLE": {"Ref": "SettingsTable"},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "CfnLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Handler": "resource.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "ESCFNProxyLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "CustomResource"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "MetricsIndex": {
      "Type": "Custom::ESProxy",
      "DependsOn": ["OpensearchDomain"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.MetricsIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {
            "Fn::Sub": "{\"settings\":{\"index.mapping.total_fields.limit\":2000}}"
          }
        }
      }
    },
    "FeedbackIndex": {
      "Type": "Custom::ESProxy",
      "DependsOn": ["OpensearchDomain"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.FeedbackIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {"Fn::Sub": "{\"settings\":{}}"}
        }
      }
    },
    "Index": {
      "Type": "Custom::ESProxy",
      "DependsOn": ["OpensearchDomain"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "index": {"Fn::Sub": "${Var.QnaIndex}"},
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "body": {
            "Fn::Sub": [
              "{\"settings\":{\"number_of_shards\":\"1\",\"index.knn\":true,\"analysis\":{\"filter\":{\"english_stop\":{\"type\":\"stop\",\"stopwords\":\"_english_\"},\"english_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"example\"]},\"english_stemmer\":{\"type\":\"stemmer\",\"language\":\"english\"},\"english_possessive_stemmer\":{\"type\":\"stemmer\",\"language\":\"possessive_english\"},\"arabic_stop\":{\"type\":\"stop\",\"stopwords\":\"_arabic_\"},\"arabic_stemmer\":{\"type\":\"stemmer\",\"language\":\"arabic\"},\"arabic_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"مثال\"]},\"armenian_stop\":{\"type\":\"stop\",\"stopwords\":\"_armenian_\"},\"armenian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"օրինակ\"]},\"armenian_stemmer\":{\"type\":\"stemmer\",\"language\":\"armenian\"},\"basque_stop\":{\"type\":\"stop\",\"stopwords\":\"_basque_\"},\"basque_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"Adibidez\"]},\"basque_stemmer\":{\"type\":\"stemmer\",\"language\":\"basque\"},\"bengali_stop\":{\"type\":\"stop\",\"stopwords\":\"_bengali_\"},\"bengali_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"উদাহরণ\"]},\"bengali_stemmer\":{\"type\":\"stemmer\",\"language\":\"bengali\"},\"brazilian_stop\":{\"type\":\"stop\",\"stopwords\":\"_brazilian_\"},\"brazilian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"exemplo\"]},\"brazilian_stemmer\":{\"type\":\"stemmer\",\"language\":\"brazilian\"},\"bulgarian_stop\":{\"type\":\"stop\",\"stopwords\":\"_bulgarian_\"},\"bulgarian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"пример\"]},\"bulgarian_stemmer\":{\"type\":\"stemmer\",\"language\":\"bulgarian\"},\"catalan_elision\":{\"type\":\"elision\",\"articles_case\":true,\"articles\":[\"d\",\"l\",\"m\",\"n\",\"s\",\"t\"]},\"catalan_stop\":{\"type\":\"stop\",\"stopwords\":\"_catalan_\"},\"catalan_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"example\"]},\"catalan_stemmer\":{\"type\":\"stemmer\",\"language\":\"catalan\"},\"czech_stop\":{\"type\":\"stop\",\"stopwords\":\"_czech_\"},\"czech_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"příklad\"]},\"czech_stemmer\":{\"type\":\"stemmer\",\"language\":\"czech\"},\"danish_stop\":{\"type\":\"stop\",\"stopwords\":\"_danish_\"},\"danish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"eksempel\"]},\"danish_stemmer\":{\"type\":\"stemmer\",\"language\":\"danish\"},\"dutch_stop\":{\"type\":\"stop\",\"stopwords\":\"_dutch_\"},\"dutch_stemmer\":{\"type\":\"stemmer\",\"language\":\"dutch\"},\"dutch_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"voorbeeld\"]},\"dutch_override\":{\"type\":\"stemmer_override\",\"rules\":[\"fiets=>fiets\",\"bromfiets=>bromfiets\",\"ei=>eier\",\"kind=>kinder\"]},\"estonian_stop\":{\"type\":\"stop\",\"stopwords\":\"_estonian_\"},\"estonian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"näide\"]},\"estonian_stemmer\":{\"type\":\"stemmer\",\"language\":\"estonian\"},\"finnish_stop\":{\"type\":\"stop\",\"stopwords\":\"_finnish_\"},\"finnish_stemmer\":{\"type\":\"stemmer\",\"language\":\"finnish\"},\"finnish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"esimerkki\"]},\"french_elision\":{\"type\":\"elision\",\"articles_case\":true,\"articles\":[\"l\",\"m\",\"t\",\"qu\",\"n\",\"s\",\"j\",\"d\",\"c\",\"jusqu\",\"quoiqu\",\"lorsqu\",\"puisqu\"]},\"french_stop\":{\"type\":\"stop\",\"stopwords\":\"_french_\"},\"french_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"Example\"]},\"french_stemmer\":{\"type\":\"stemmer\",\"language\":\"light_french\"},\"galician_stop\":{\"type\":\"stop\",\"stopwords\":\"_galician_\"},\"galician_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"exemplo\"]},\"galician_stemmer\":{\"type\":\"stemmer\",\"language\":\"galician\"},\"german_stop\":{\"type\":\"stop\",\"stopwords\":\"_german_\"},\"german_stemmer\":{\"type\":\"stemmer\",\"language\":\"light_german\"},\"german_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"Beispiel\"]},\"greek_stop\":{\"type\":\"stop\",\"stopwords\":\"_greek_\"},\"greek_lowercase\":{\"type\":\"lowercase\",\"language\":\"greek\"},\"greek_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"παράδειγμα\"]},\"greek_stemmer\":{\"type\":\"stemmer\",\"language\":\"greek\"},\"hindi_stop\":{\"type\":\"stop\",\"stopwords\":\"_hindi_\"},\"hindi_stemmer\":{\"type\":\"stemmer\",\"language\":\"hindi\"},\"hindi_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"उदाहरण\"]},\"hungarian_stop\":{\"type\":\"stop\",\"stopwords\":\"_hungarian_\"},\"hungarian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"példa\"]},\"hungarian_stemmer\":{\"type\":\"stemmer\",\"language\":\"hungarian\"},\"indonesian_stop\":{\"type\":\"stop\",\"stopwords\":\"_indonesian_\"},\"indonesian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"contoh\"]},\"indonesian_stemmer\":{\"type\":\"stemmer\",\"language\":\"indonesian\"},\"irish_hyphenation\":{\"type\":\"stop\",\"stopwords\":[\"h\",\"n\",\"t\"],\"ignore_case\":true},\"irish_elision\":{\"type\":\"elision\",\"articles\":[\"d\",\"m\",\"b\"],\"articles_case\":true},\"irish_stop\":{\"type\":\"stop\",\"stopwords\":\"_irish_\"},\"irish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"sampla\"]},\"irish_lowercase\":{\"type\":\"lowercase\",\"language\":\"irish\"},\"irish_stemmer\":{\"type\":\"stemmer\",\"language\":\"irish\"},\"italian_elision\":{\"type\":\"elision\",\"articles\":[\"c\",\"l\",\"all\",\"dall\",\"dell\",\"nell\",\"sull\",\"coll\",\"pell\",\"gl\",\"agl\",\"dagl\",\"degl\",\"negl\",\"sugl\",\"un\",\"m\",\"t\",\"s\",\"v\",\"d\"],\"articles_case\":true},\"italian_stop\":{\"type\":\"stop\",\"stopwords\":\"_italian_\"},\"italian_stemmer\":{\"type\":\"stemmer\",\"language\":\"light_italian\"},\"italian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"esempio\"]},\"latvian_stop\":{\"type\":\"stop\",\"stopwords\":\"_latvian_\"},\"latvian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"piemērs\"]},\"latvian_stemmer\":{\"type\":\"stemmer\",\"language\":\"latvian\"},\"lithuanian_stop\":{\"type\":\"stop\",\"stopwords\":\"_lithuanian_\"},\"lithuanian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"pavyzdys\"]},\"lithuanian_stemmer\":{\"type\":\"stemmer\",\"language\":\"lithuanian\"},\"norwegian_stop\":{\"type\":\"stop\",\"stopwords\":\"_norwegian_\"},\"norwegian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"eksempel\"]},\"norwegian_stemmer\":{\"type\":\"stemmer\",\"language\":\"norwegian\"},\"portuguese_stop\":{\"type\":\"stop\",\"stopwords\":\"_portuguese_\"},\"portuguese_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"exemplo\"]},\"portuguese_stemmer\":{\"type\":\"stemmer\",\"language\":\"light_portuguese\"},\"romanian_stop\":{\"type\":\"stop\",\"stopwords\":\"_romanian_\"},\"romanian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"exemplu\"]},\"romanian_stemmer\":{\"type\":\"stemmer\",\"language\":\"romanian\"},\"russian_stop\":{\"type\":\"stop\",\"stopwords\":\"_russian_\"},\"russian_stemmer\":{\"type\":\"stemmer\",\"language\":\"russian\"},\"russian_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"пример\"]},\"sorani_stop\":{\"type\":\"stop\",\"stopwords\":\"_sorani_\"},\"sorani_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"mînak\"]},\"sorani_stemmer\":{\"type\":\"stemmer\",\"language\":\"sorani\"},\"spanish_stop\":{\"type\":\"stop\",\"stopwords\":\"_spanish_\"},\"spanish_stemmer\":{\"type\":\"stemmer\",\"language\":\"light_spanish\"},\"spanish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"ejemplo\"]},\"swedish_stop\":{\"type\":\"stop\",\"stopwords\":\"_swedish_\"},\"swedish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"exempel\"]},\"swedish_stemmer\":{\"type\":\"stemmer\",\"language\":\"swedish\"},\"turkish_stop\":{\"type\":\"stop\",\"stopwords\":\"_turkish_\"},\"turkish_lowercase\":{\"type\":\"lowercase\",\"language\":\"turkish\"},\"turkish_keywords\":{\"type\":\"keyword_marker\",\"keywords\":[\"örnek\"]},\"turkish_stemmer\":{\"type\":\"stemmer\",\"language\":\"turkish\"},\"thai_stop\":{\"type\":\"stop\",\"stopwords\":\"_thai_\"}},\"analyzer\":{\"rebuilt_English\":{\"type\":\"custom\",\"tokenizer\":\"standard\",\"filter\":[\"english_possessive_stemmer\",\"lowercase\",\"english_stop\",\"english_keywords\",\"english_stemmer\"]},\"rebuilt_English_unique\":{\"type\":\"custom\",\"tokenizer\":\"standard\",\"filter\":[\"english_possessive_stemmer\",\"lowercase\",\"english_stop\",\"english_keywords\",\"english_stemmer\",\"unique\"]},\"rebuilt_Arabic\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"decimal_digit\",\"arabic_stop\",\"arabic_normalization\",\"arabic_keywords\",\"arabic_stemmer\"]},\"rebuilt_Armenian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"armenian_stop\",\"armenian_keywords\",\"armenian_stemmer\"]},\"rebuilt_Basque\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"basque_stop\",\"basque_keywords\",\"basque_stemmer\"]},\"rebuilt_Bengali\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"decimal_digit\",\"bengali_keywords\",\"indic_normalization\",\"bengali_normalization\",\"bengali_stop\",\"bengali_stemmer\"]},\"rebuilt_Brazilian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"brazilian_stop\",\"brazilian_keywords\",\"brazilian_stemmer\"]},\"rebuilt_Bulgarian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"bulgarian_stop\",\"bulgarian_keywords\",\"bulgarian_stemmer\"]},\"rebuilt_Catalan\":{\"tokenizer\":\"standard\",\"filter\":[\"catalan_elision\",\"lowercase\",\"catalan_stop\",\"catalan_keywords\",\"catalan_stemmer\"]},\"rebuilt_Czech\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"czech_stop\",\"czech_keywords\",\"czech_stemmer\"]},\"rebuilt_Danish\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"danish_stop\",\"danish_keywords\",\"danish_stemmer\"]},\"rebuilt_Dutch\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"dutch_stop\",\"dutch_keywords\",\"dutch_override\",\"dutch_stemmer\"]},\"rebuilt_Estonian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"estonian_stop\",\"estonian_keywords\",\"estonian_stemmer\"]},\"rebuilt_Finnish\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"finnish_stop\",\"finnish_keywords\",\"finnish_stemmer\"]},\"rebuilt_French\":{\"tokenizer\":\"standard\",\"filter\":[\"french_elision\",\"lowercase\",\"french_stop\",\"french_keywords\",\"french_stemmer\"]},\"rebuilt_Galician\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"galician_stop\",\"galician_keywords\",\"galician_stemmer\"]},\"rebuilt_German\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"german_stop\",\"german_keywords\",\"german_normalization\",\"german_stemmer\"]},\"rebuilt_Greek\":{\"tokenizer\":\"standard\",\"filter\":[\"greek_lowercase\",\"greek_stop\",\"greek_keywords\",\"greek_stemmer\"]},\"rebuilt_Hindi\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"decimal_digit\",\"hindi_keywords\",\"indic_normalization\",\"hindi_normalization\",\"hindi_stop\",\"hindi_stemmer\"]},\"rebuilt_Hungarian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"hungarian_stop\",\"hungarian_keywords\",\"hungarian_stemmer\"]},\"rebuilt_Indonesian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"indonesian_stop\",\"indonesian_keywords\",\"indonesian_stemmer\"]},\"rebuilt_Irish\":{\"tokenizer\":\"standard\",\"filter\":[\"irish_hyphenation\",\"irish_elision\",\"irish_lowercase\",\"irish_stop\",\"irish_keywords\",\"irish_stemmer\"]},\"rebuilt_Italian\":{\"tokenizer\":\"standard\",\"filter\":[\"italian_elision\",\"lowercase\",\"italian_stop\",\"italian_keywords\",\"italian_stemmer\"]},\"rebuilt_Latvian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"latvian_stop\",\"latvian_keywords\",\"latvian_stemmer\"]},\"rebuilt_Lithuanian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"lithuanian_stop\",\"lithuanian_keywords\",\"lithuanian_stemmer\"]},\"rebuilt_Norwegian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"norwegian_stop\",\"norwegian_keywords\",\"norwegian_stemmer\"]},\"rebuilt_Portuguese\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"portuguese_stop\",\"portuguese_keywords\",\"portuguese_stemmer\"]},\"rebuilt_Romanian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"romanian_stop\",\"romanian_keywords\",\"romanian_stemmer\"]},\"rebuilt_Russian\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"russian_stop\",\"russian_keywords\",\"russian_stemmer\"]},\"rebuilt_Sorani\":{\"tokenizer\":\"standard\",\"filter\":[\"sorani_normalization\",\"lowercase\",\"decimal_digit\",\"sorani_stop\",\"sorani_keywords\",\"sorani_stemmer\"]},\"rebuilt_Spanish\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"spanish_stop\",\"spanish_keywords\",\"spanish_stemmer\"]},\"rebuilt_Swedish\":{\"tokenizer\":\"standard\",\"filter\":[\"lowercase\",\"swedish_stop\",\"swedish_keywords\",\"swedish_stemmer\"]},\"rebuilt_Turkish\":{\"tokenizer\":\"standard\",\"filter\":[\"apostrophe\",\"turkish_lowercase\",\"turkish_stop\",\"turkish_keywords\",\"turkish_stemmer\"]},\"rebuilt_Thai\":{\"tokenizer\":\"thai\",\"filter\":[\"lowercase\",\"decimal_digit\",\"thai_stop\"]}}}},\"mappings\":{\"properties\":{\"qid\":{\"type\":\"keyword\"},\"quniqueterms\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"questions\":{\"type\":\"nested\",\"properties\":{\"q\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"q_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}}}},\"a\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"a_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}},\"t\":{\"type\":\"text\",\"analyzer\":\"whitespace\"},\"r\":{\"properties\":{\"imageUrl\":{\"type\":\"keyword\"},\"title\":{\"type\":\"text\"}}},\"l\":{\"type\":\"keyword\"},\"passage\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"passage_vector\":{\"type\":\"knn_vector\",\"dimension\":\"${EmbeddingsDimensions}\",\"method\":{\"name\":\"hnsw\",\"space_type\":\"cosinesimil\",\"engine\":\"nmslib\"}},\"question\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"incorrectAnswers\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"},\"correctAnswers\":{\"type\":\"text\",\"analyzer\":\"rebuilt_${Language}\"}}}}",
              {
                "EmbeddingsDimensions": {
                  "Fn::If": [
                    "EmbeddingsEnable",
                    {
                      "Fn::If": [
                        "EmbeddingsLambda",
                        {"Ref": "EmbeddingsLambdaDimensions"},
                        {
                          "Fn::If": [
                            "EmbeddingsBedrock",
                            {
                              "Fn::FindInMap": [
                                "BedrockDefaults",
                                {"Ref": "EmbeddingsBedrockModelId"},
                                "EmbeddingsDimensions"
                              ]
                            },
                            "INVALID EMBEDDINGS API - Cannot determine dimensions"
                          ]
                        }
                      ]
                    },
                    "1"
                  ]
                }
              }
            ]
          }
        }
      }
    },
    "OpensearchDashboards": {
      "Type": "Custom::ESProxy",
      "DependsOn": ["Index"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["ESCFNProxyLambda", "Arn"]},
        "create": {
          "endpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "path": "/_dashboards/api/opensearch-dashboards/dashboards/import?force=true",
          "method": "POST",
          "headers": {"osd-xsrf": "true"},
          "body": {
            "version": "1.3.0",
            "objects": [
              {
                "id": "052b1350-a37d-11ea-8370-0f1df276cae1",
                "type": "dashboard",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzAsMV0=",
                "attributes": {
                  "hits": "0",
                  "timeFrom": "now/w",
                  "timeTo": "now/w",
                  "refreshInterval": {"value": "0", "pause": "true"},
                  "description": "Visualize QnABot usage, see what your users are asking, and use the \"No Hits\" and \"Feedback\" charts to assess where you should add or tune QnABot content to make the bot smarter. ",
                  "title": "QnABot Dashboard",
                  "timeRestore": "false",
                  "version": "1",
                  "panelsJSON": "[{\"embeddableConfig\":{\"legendOpen\":false,\"vis\":{\"legendOpen\":true}},\"gridData\":{\"h\":15,\"i\":\"fb115451-3b8a-436f-b916-8a04db4e9d70\",\"w\":17,\"x\":0,\"y\":0},\"panelIndex\":\"fb115451-3b8a-436f-b916-8a04db4e9d70\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_0\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"5e25d094-b045-4afe-953d-2d619b05b716\",\"w\":14,\"x\":34,\"y\":0},\"panelIndex\":\"5e25d094-b045-4afe-953d-2d619b05b716\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_1\"},{\"embeddableConfig\":{\"legendOpen\":false,\"vis\":{\"legendOpen\":true}},\"gridData\":{\"h\":15,\"i\":\"cf017f39-a5a3-4d3a-9561-862f4c2eb3c5\",\"w\":17,\"x\":17,\"y\":0},\"panelIndex\":\"cf017f39-a5a3-4d3a-9561-862f4c2eb3c5\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_2\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"b9b730b1-b3de-42f9-a4de-69197d934a93\",\"w\":24,\"x\":0,\"y\":15},\"panelIndex\":\"b9b730b1-b3de-42f9-a4de-69197d934a93\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_3\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"472ff8b6-83bf-4e4d-a8a5-44ce8f7e3dac\",\"w\":24,\"x\":24,\"y\":15},\"panelIndex\":\"472ff8b6-83bf-4e4d-a8a5-44ce8f7e3dac\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_4\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"92e5cbb2-fa56-4f15-b7b1-72c11e0bebfc\",\"w\":24,\"x\":0,\"y\":30},\"panelIndex\":\"92e5cbb2-fa56-4f15-b7b1-72c11e0bebfc\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_5\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"7ca7cdb0-2472-4eb0-bf7e-ae90f238f869\",\"w\":24,\"x\":24,\"y\":30},\"panelIndex\":\"7ca7cdb0-2472-4eb0-bf7e-ae90f238f869\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_6\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":8,\"i\":\"cba70b74-3264-4153-87d2-68c24b552efa\",\"w\":10,\"x\":0,\"y\":45},\"panelIndex\":\"cba70b74-3264-4153-87d2-68c24b552efa\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_7\"},{\"embeddableConfig\":{},\"gridData\":{\"h\":15,\"i\":\"4fd7e920-26dd-4d02-8235-bcdff5725991\",\"w\":24,\"x\":10,\"y\":45},\"panelIndex\":\"4fd7e920-26dd-4d02-8235-bcdff5725991\",\"version\":\"7.9.1\",\"panelRefName\":\"panel_8\"}]",
                  "optionsJSON": "{\"hidePanelTitles\":false,\"useMargins\":true}",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[]}"
                  }
                },
                "references": [
                  {
                    "name": "panel_0",
                    "id": "a66d5ed0-a378-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_1",
                    "id": "d905b930-a37a-11ea-a346-0f81312f0c3c",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_2",
                    "id": "12d24870-e16c-11ea-b423-5f0e2ad2220e",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_3",
                    "id": "68d7c450-a37a-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_4",
                    "id": "d68ac390-a379-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_5",
                    "id": "6759e170-a37b-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_6",
                    "id": "985eb570-a37b-11ea-8370-0f1df276cae1",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_7",
                    "id": "2031f610-a4c1-11ea-a012-c353d737e5ec",
                    "type": "visualization"
                  },
                  {
                    "name": "panel_8",
                    "id": "49e34620-9198-11eb-ab91-adc4ba11519d",
                    "type": "visualization"
                  }
                ],
                "migrationVersion": {"dashboard": "7.9.3"}
              },
              {
                "id": "a66d5ed0-a378-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Requests",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Requests\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":true,\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"dimensions\":{\"x\":{\"accessor\":0,\"format\":{\"id\":\"date\",\"params\":{\"pattern\":\"HH:mm:ss\"}},\"params\":{\"date\":true,\"interval\":\"PT30S\",\"format\":\"HH:mm:ss\",\"bounds\":{\"min\":\"2020-07-06T21:55:15.220Z\",\"max\":\"2020-07-06T22:25:15.220Z\"}},\"aggType\":\"date_histogram\"},\"y\":[{\"accessor\":1,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"cardinality\"}]},\"grid\":{\"categoryLines\":false},\"labels\":{\"show\":false},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"thresholdLine\":{\"color\":\"#34130C\",\"show\":false,\"style\":\"full\",\"value\":10,\"width\":1},\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"datetime\",\"timeRange\":{\"from\":\"now-30m\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Requests\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"entireRequest.sentiment.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Sentiment\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "d905b930-a37a-11ea-a346-0f81312f0c3c",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzIsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Client Types",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Client Types\",\"type\":\"pie\",\"params\":{\"type\":\"pie\",\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"isDonut\":false,\"labels\":{\"show\":false,\"values\":true,\"last_level\":true,\"truncate\":100},\"dimensions\":{\"metric\":{\"accessor\":1,\"format\":{\"id\":\"number\"},\"params\":{},\"aggType\":\"count\"},\"buckets\":[{\"accessor\":0,\"format\":{\"id\":\"terms\",\"params\":{\"id\":\"string\",\"otherBucketLabel\":\"Other\",\"missingBucketLabel\":\"Missing\"}},\"params\":{},\"aggType\":\"terms\"}]}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"clientType.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Client Types\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "12d24870-e16c-11ea-b423-5f0e2ad2220e",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzMsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Requests AnswerSource",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"type\":\"histogram\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"datetime\",\"timeRange\":{\"from\":\"2020-08-18T15:44:48.334Z\",\"to\":\"2020-08-18T15:59:17.582Z\"},\"useNormalizedEsInterval\":true,\"scaleMetricValues\":false,\"interval\":\"auto\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Requests\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"entireResponse.answerSource.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Source\"}}],\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"filter\":true,\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"dimensions\":{\"x\":{\"accessor\":0,\"aggType\":\"date_histogram\",\"format\":{\"id\":\"date\",\"params\":{\"pattern\":\"HH:mm:ss\"}},\"params\":{\"bounds\":{\"max\":\"2020-07-06T22:25:15.220Z\",\"min\":\"2020-07-06T21:55:15.220Z\"},\"date\":true,\"format\":\"HH:mm:ss\",\"interval\":\"PT30S\"}},\"y\":[{\"accessor\":1,\"aggType\":\"cardinality\",\"format\":{\"id\":\"number\"},\"params\":{}}]},\"grid\":{\"categoryLines\":false},\"labels\":{\"show\":false},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Count\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"thresholdLine\":{\"color\":\"#34130C\",\"show\":false,\"style\":\"full\",\"value\":10,\"width\":1},\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Count\"},\"type\":\"value\"}]},\"title\":\"Requests AnswerSource\"}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "68d7c450-a37a-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzQsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Logged Utterances",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Logged Utterances\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":1000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Logged Utterances\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "d68ac390-a379-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzUsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "No Hits",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"entireResponse.got_hits:0\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"No Hits\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":1000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"No Hits\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "6759e170-a37b-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzYsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Positive Feedback",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"feedback:correct\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Positive Feedback\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"string\",\"params\":{}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":100,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Thumbs Up\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Feedback",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "985eb570-a37b-11ea-8370-0f1df276cae1",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzcsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "Negative Feedback",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"feedback:incorrect\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Negative Feedback\",\"type\":\"tagcloud\",\"params\":{\"scale\":\"linear\",\"orientation\":\"single\",\"minFontSize\":18,\"maxFontSize\":72,\"showLabel\":true,\"metric\":{\"type\":\"vis_dimension\",\"accessor\":1,\"format\":{\"id\":\"string\",\"params\":{}}},\"bucket\":{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"terms\",\"params\":{\"id\":\"string\",\"otherBucketLabel\":\"Other\",\"missingBucketLabel\":\"Missing\"}}}},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"utterance.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":100,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Thumbs Down\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Feedback",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "2031f610-a4c1-11ea-a012-c353d737e5ec",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzgsMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{}",
                  "title": "QnAItemCount",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"QnAItemCount\",\"type\":\"metric\",\"params\":{\"metric\":{\"percentageMode\":false,\"useRanges\":false,\"colorSchema\":\"Green to Red\",\"metricColorMode\":\"None\",\"colorsRange\":[{\"type\":\"range\",\"from\":0,\"to\":10000}],\"labels\":{\"show\":true},\"invertColors\":false,\"style\":{\"bgFill\":\"#000\",\"bgColor\":false,\"labelColor\":false,\"subText\":\"\",\"fontSize\":60}},\"dimensions\":{\"metrics\":[{\"type\":\"vis_dimension\",\"accessor\":0,\"format\":{\"id\":\"number\",\"params\":{}}}]},\"addTooltip\":true,\"addLegend\":false,\"type\":\"metric\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"QnA Item Count\"}}]}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "QnaItems",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "49e34620-9198-11eb-ab91-adc4ba11519d",
                "type": "visualization",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzksMV0=",
                "attributes": {
                  "description": "",
                  "uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":0,\"direction\":\"asc\"}}}}",
                  "title": "Answer Sources",
                  "version": "1",
                  "kibanaSavedObjectMeta": {
                    "searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"
                  },
                  "visState": "{\"title\":\"Answer Sources\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"entireResponse.result.answersource.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Answer Source\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"
                },
                "references": [
                  {
                    "name": "kibanaSavedObjectMeta.searchSourceJSON.index",
                    "id": "Metrics",
                    "type": "index-pattern"
                  }
                ],
                "migrationVersion": {"visualization": "7.10.0"}
              },
              {
                "id": "Metrics",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEwLDFd",
                "attributes": {
                  "timeFieldName": "datetime",
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"answer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"answer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"answer\"}}},{\"name\":\"clientType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"clientType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"clientType\"}}},{\"name\":\"datetime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._clientType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._clientType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._clientType\"}}},{\"name\":\"entireRequest._event.bot.alias\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.alias.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.alias\"}}},{\"name\":\"entireRequest._event.bot.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.name\"}}},{\"name\":\"entireRequest._event.bot.version\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.bot.version.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.bot.version\"}}},{\"name\":\"entireRequest._event.currentIntent.confirmationStatus\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.confirmationStatus.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.confirmationStatus\"}}},{\"name\":\"entireRequest._event.currentIntent.name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.name\"}}},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slotDetails.slot.originalValue\"}}},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slotDetails.slot.resolutions.value\"}}},{\"name\":\"entireRequest._event.currentIntent.slots.slot\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.currentIntent.slots.slot.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.currentIntent.slots.slot\"}}},{\"name\":\"entireRequest._event.errorFound\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._event.inputTranscript\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.inputTranscript.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.inputTranscript\"}}},{\"name\":\"entireRequest._event.invocationSource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.invocationSource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.invocationSource\"}}},{\"name\":\"entireRequest._event.messageVersion\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.messageVersion.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.messageVersion\"}}},{\"name\":\"entireRequest._event.outputDialogMode\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.outputDialogMode.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.outputDialogMode\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.confirmationStatus\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.dialogActionType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.dialogActionType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.dialogActionType\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.fulfillmentState\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.intentName\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.intentName.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.intentName\"}}},{\"name\":\"entireRequest._event.recentIntentSummaryView.slots.slot\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.recentIntentSummaryView.slots.slot.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.recentIntentSummaryView.slots.slot\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabot_gotanswer\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabot_qid\"}}},{\"name\":\"entireRequest._event.sessionAttributes.qnabotcontext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.sessionAttributes.qnabotcontext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.sessionAttributes.qnabotcontext\"}}},{\"name\":\"entireRequest._event.userId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._event.userId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._event.userId\"}}},{\"name\":\"entireRequest._info.es.address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.address\"}}},{\"name\":\"entireRequest._info.es.index\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.index.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.index\"}}},{\"name\":\"entireRequest._info.es.service.proxy\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.service.proxy.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.service.proxy\"}}},{\"name\":\"entireRequest._info.es.service.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.service.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.service.qid\"}}},{\"name\":\"entireRequest._info.es.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._info.es.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._info.es.type\"}}},{\"name\":\"entireRequest._preferredResponseType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._preferredResponseType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._preferredResponseType\"}}},{\"name\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ALT_SEARCH_KENDRA_INDEXES\"}}},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_ALEXA_LAUNCH_MESSAGE\"}}},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_ALEXA_STOP_MESSAGE\"}}},{\"name\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.DEFAULT_USER_POOL_JWKS_URL\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_DEFAULT_MSG\"}}},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_MAX_RETRIES\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ELICIT_RESPONSE_RETRY_MESSAGE\"}}},{\"name\":\"entireRequest._settings.EMPTYMESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.EMPTYMESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.EMPTYMESSAGE\"}}},{\"name\":\"entireRequest._settings.ENABLE_DEBUG_RESPONSES\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_MULTI_LANGUAGE_SUPPORT\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_REDACTING\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENABLE_SENTIMENT_SUPPORT\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ENFORCE_VERIFIED_IDENTITY\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ERRORMESSAGE\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ERRORMESSAGE.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ERRORMESSAGE\"}}},{\"name\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_KEYWORD_SYNTAX_TYPES\"}}},{\"name\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_MINIMUM_SHOULD_MATCH\"}}},{\"name\":\"entireRequest._settings.ES_NO_HITS_QUESTION\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_NO_HITS_QUESTION.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_NO_HITS_QUESTION\"}}},{\"name\":\"entireRequest._settings.ES_PHRASE_BOOST\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_PHRASE_BOOST.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_PHRASE_BOOST\"}}},{\"name\":\"entireRequest._settings.ES_SCORE_ANSWER_FIELD\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.ES_SYNTAX_CONFIDENCE_LIMIT\"}}},{\"name\":\"entireRequest._settings.ES_USE_FUZZY_MATCH\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.ES_USE_KEYWORD_FILTERS\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_CONFIG_MAX_RETRIES\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_CONFIG_RETRY_DELAY\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_ES_FALLBACK\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.KENDRA_FAQ_INDEX\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.KENDRA_FAQ_INDEX.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.KENDRA_FAQ_INDEX\"}}},{\"name\":\"entireRequest._settings.MINIMUM_CONFIDENCE_SCORE\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.NO_VERIFIED_IDENTITY_QUESTION\"}}},{\"name\":\"entireRequest._settings.REDACTING_REGEX\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.REDACTING_REGEX.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.REDACTING_REGEX\"}}},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.SMS_HINT_REMINDER\"}}},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_ENABLE\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._settings.SMS_HINT_REMINDER_INTERVAL_HRS\"}}},{\"name\":\"entireRequest._type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._type\"}}},{\"name\":\"entireRequest._userId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userId\"}}},{\"name\":\"entireRequest._userInfo.FirstSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.FirstSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.FirstSeen\"}}},{\"name\":\"entireRequest._userInfo.InteractionCount\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._userInfo.LastSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.LastSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.LastSeen\"}}},{\"name\":\"entireRequest._userInfo.TimeSinceLastInteraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest._userInfo.UserId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.UserId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.UserId\"}}},{\"name\":\"entireRequest._userInfo.isVerifiedIdentity\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest._userInfo.isVerifiedIdentity.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest._userInfo.isVerifiedIdentity\"}}},{\"name\":\"entireRequest.kendraResultsCached\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.kendraResultsCached.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.kendraResultsCached\"}}},{\"name\":\"entireRequest.question\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.question.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.question\"}}},{\"name\":\"entireRequest.sentiment\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.sentiment.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.sentiment\"}}},{\"name\":\"entireRequest.session.qnabot_gotanswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest.session.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabot_qid\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraIndexId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraQueryId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraResponsibleQid\"}}},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.kendra.kendraResultId\"}}},{\"name\":\"entireRequest.session.qnabotcontext.navigation.hasParent\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireRequest.session.qnabotcontext.navigation.next\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.navigation.next.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.navigation.next\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.a.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.a\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.q\"}}},{\"name\":\"entireRequest.session.qnabotcontext.previous.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireRequest.session.qnabotcontext.previous.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireRequest.session.qnabotcontext.previous.qid\"}}},{\"name\":\"entireResponse._userInfo.FirstSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.FirstSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.FirstSeen\"}}},{\"name\":\"entireResponse._userInfo.InteractionCount\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse._userInfo.LastSeen\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.LastSeen.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.LastSeen\"}}},{\"name\":\"entireResponse._userInfo.TimeSinceLastInteraction\",\"type\":\"number\",\"esTypes\":[\"float\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse._userInfo.UserId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.UserId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.UserId\"}}},{\"name\":\"entireResponse._userInfo.isVerifiedIdentity\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse._userInfo.isVerifiedIdentity.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse._userInfo.isVerifiedIdentity\"}}},{\"name\":\"entireResponse.answerSource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.answerSource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.answerSource\"}}},{\"name\":\"entireResponse.card.send\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.card.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.text\"}}},{\"name\":\"entireResponse.card.title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.title.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.title\"}}},{\"name\":\"entireResponse.card.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.card.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.card.url\"}}},{\"name\":\"entireResponse.got_hits\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.QueryId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.QueryId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.QueryId\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Key\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.Value.TextWithHighlightsValue.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.AdditionalAttributes.ValueType\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Key\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentAttributes.Value.StringValue\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentExcerpt.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentId\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.BeginOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.EndOffset\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Highlights.TopAnswer\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentTitle.Text\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.DocumentURI\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.Id\"}}},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.ResultItems.Type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.ResultItems.Type\"}}},{\"name\":\"entireResponse.kendraResultsCached.TotalNumberOfResults\",\"type\":\"number\",\"esTypes\":[\"long\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.kendraResultsCached.originalKendraIndexId\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.kendraResultsCached.originalKendraIndexId.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.kendraResultsCached.originalKendraIndexId\"}}},{\"name\":\"entireResponse.message\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.message.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.message\"}}},{\"name\":\"entireResponse.plainMessage\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.plainMessage.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.plainMessage\"}}},{\"name\":\"entireResponse.result.a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.a.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.a\"}}},{\"name\":\"entireResponse.result.answersource\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.answersource.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.answersource\"}}},{\"name\":\"entireResponse.result.autotranslate.a\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"entireResponse.result.l\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.l.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.l\"}}},{\"name\":\"entireResponse.result.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.q\"}}},{\"name\":\"entireResponse.result.qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.qid\"}}},{\"name\":\"entireResponse.result.questions.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.questions.q.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.questions.q\"}}},{\"name\":\"entireResponse.result.quniqueterms\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.quniqueterms.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.quniqueterms\"}}},{\"name\":\"entireResponse.result.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.result.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.result.type\"}}},{\"name\":\"entireResponse.session.appContext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.appContext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.appContext\"}}},{\"name\":\"entireResponse.session.qnabot_gotanswer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabot_gotanswer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabot_gotanswer\"}}},{\"name\":\"entireResponse.session.qnabot_qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabot_qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabot_qid\"}}},{\"name\":\"entireResponse.session.qnabotcontext\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.session.qnabotcontext.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.session.qnabotcontext\"}}},{\"name\":\"entireResponse.type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"entireResponse.type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"entireResponse.type\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"qid\"}}},{\"name\":\"topic\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"topic.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"topic\"}}},{\"name\":\"utterance\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"utterance.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"utterance\"}}}]",
                  "title": "<INDEX_METRICS>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              },
              {
                "id": "Feedback",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzExLDFd",
                "attributes": {
                  "timeFieldName": "datetime",
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"alternate\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alternate.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alternate\"}}},{\"name\":\"answer\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"answer.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"answer\"}}},{\"name\":\"datetime\",\"type\":\"date\",\"esTypes\":[\"date\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"feedback\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"feedback.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"feedback\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"qid.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"qid\"}}},{\"name\":\"utterance\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"utterance.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"utterance\"}}}]",
                  "title": "<INDEX_FEEDBACK>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              },
              {
                "id": "QnaItems",
                "type": "index-pattern",
                "namespaces": ["default"],
                "updated_at": "2022-12-04T21:21:27.535Z",
                "version": "WzEyLDFd",
                "attributes": {
                  "fields": "[{\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"a\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.markdown\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.markdown.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alt.markdown\"}}},{\"name\":\"alt.ssml\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"alt.ssml.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"alt.ssml\"}}},{\"name\":\"args\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"args.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"args\"}}},{\"name\":\"conditionalChaining\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"conditionalChaining.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"conditionalChaining\"}}},{\"name\":\"correctAnswers\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.response_sessionattr_namespace\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.response_sessionattr_namespace.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"elicitResponse.response_sessionattr_namespace\"}}},{\"name\":\"elicitResponse.responsebot_hook\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"elicitResponse.responsebot_hook.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"elicitResponse.responsebot_hook\"}}},{\"name\":\"incorrectAnswers\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"l\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"next\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"next.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"next\"}}},{\"name\":\"qid\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"question\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"questions.q\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"quiz\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"quiz.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"quiz\"}}},{\"name\":\"quniqueterms\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.buttons.text\"}}},{\"name\":\"r.buttons.value\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.buttons.value.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.buttons.value\"}}},{\"name\":\"r.imageUrl\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"r.subTitle\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.subTitle.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.subTitle\"}}},{\"name\":\"r.text\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.text.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.text\"}}},{\"name\":\"r.title\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.url\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"r.url.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"r.url\"}}},{\"name\":\"responses.correct\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.correct.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.correct\"}}},{\"name\":\"responses.end\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.end.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.end\"}}},{\"name\":\"responses.incorrect\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"responses.incorrect.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"responses.incorrect\"}}},{\"name\":\"selected\",\"type\":\"boolean\",\"esTypes\":[\"boolean\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"t\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"type\",\"type\":\"string\",\"esTypes\":[\"text\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"type.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"type\"}}}]",
                  "title": "<INDEX_QNA>"
                },
                "references": [],
                "migrationVersion": {"index-pattern": "7.6.0"}
              }
            ]
          },
          "replaceTokenInBody": [
            {"f": "<INDEX_QNA>", "r": {"Fn::Sub": "${Var.QnaIndex}"}},
            {"f": "<INDEX_METRICS>", "r": {"Fn::Sub": "${Var.MetricsIndex}"}},
            {"f": "<INDEX_FEEDBACK>", "r": {"Fn::Sub": "${Var.FeedbackIndex}"}}
          ]
        }
      }
    },
    "OpenSearchLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Condition": "FGACEnabled",
      "Properties": {
        "LogGroupName": {
          "Fn::Sub": "/aws/opensearch/${AWS::StackName}-${ESVar.ESDomain}"
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {"id": "W86", "reason": "LogGroup is encrypted by default."}
          ]
        },
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "OpenSearchLogGroupResourcePolicy": {
      "Type": "AWS::Logs::ResourcePolicy",
      "Condition": "FGACEnabled",
      "DependsOn": ["OpenSearchLogGroup"],
      "Properties": {
        "PolicyName": {
          "Fn::Sub": "${AWS::StackName}-AWSQnaBotOpenSearchLogResourcePolicy"
        },
        "PolicyDocument": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"opensearchservice.amazonaws.com\"},\"Action\":[\"logs:PutLogEvents\",\"logs:CreateLogStream\"],\"Resource\":[\"arn:*:logs:*:*:log-group:/aws/opensearch/*\"]}]}"
      }
    },
    "OpenSearchCognitoAccessUpdates": {
      "DependsOn": [
        "OpensearchDomain",
        "Index",
        "FeedbackIndex",
        "MetricsIndex",
        "ESCognitoRole",
        "OpenSearchLogGroupResourcePolicy"
      ],
      "Type": "Custom::OpenSearchUpdates",
      "Condition": "FGACEnabled",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "DomainName": {"Fn::GetAtt": ["ESVar", "ESDomain"]},
        "AccessPolicies": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": [{"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]}]
              },
              "Action": ["es:ESHttp*"],
              "Resource": [
                {"Fn::Join": ["", [{"Fn::GetAtt": ["ESVar", "ESArn"]}, "/*"]]}
              ]
            }
          ]
        },
        "LogPublishingOptions": {
          "SEARCH_SLOW_LOGS": {
            "CloudWatchLogsLogGroupArn": {
              "Fn::GetAtt": ["OpenSearchLogGroup", "Arn"]
            },
            "Enabled": true
          },
          "INDEX_SLOW_LOGS": {
            "CloudWatchLogsLogGroupArn": {
              "Fn::GetAtt": ["OpenSearchLogGroup", "Arn"]
            },
            "Enabled": true
          },
          "AUDIT_LOGS": {
            "CloudWatchLogsLogGroupArn": {
              "Fn::GetAtt": ["OpenSearchLogGroup", "Arn"]
            },
            "Enabled": true
          },
          "ES_APPLICATION_LOGS": {
            "CloudWatchLogsLogGroupArn": {
              "Fn::GetAtt": ["OpenSearchLogGroup", "Arn"]
            },
            "Enabled": true
          }
        },
        "AdvancedSecurityOptions": {
          "Enabled": true,
          "AnonymousAuthEnabled": false,
          "InternalUserDatabaseEnabled": false,
          "MasterUserOptions": {
            "MasterUserARN": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]}
          }
        }
      }
    },
    "LexAccessPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["lex:RecognizeText", "lex:RecognizeUtterance"],
              "Resource": [
                {
                  "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:*"
                }
              ]
            },
            {
              "Effect": "Allow",
              "Action": ["polly:SynthesizeSpeech"],
              "Resource": [
                {
                  "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:*"
                }
              ]
            }
          ]
        },
        "Roles": {
          "Fn::If": [
            "Public",
            [
              {"Ref": "AdminRole"},
              {"Ref": "UnauthenticatedRole"},
              {"Ref": "UserRole"}
            ],
            [{"Ref": "AdminRole"}, {"Ref": "UserRole"}]
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W13",
              "reason": "This policy is required to have * resource"
            }
          ]
        }
      }
    },
    "ApiGatewayCloudWatchLogsRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": ["apigateway.amazonaws.com"]},
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Policies": [
          {
            "PolicyName": "ApiGatewayLogsPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["logs:DescribeLogGroups"],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:DescribeLogStreams",
                    "logs:PutLogEvents",
                    "logs:GetLogEvents",
                    "logs:FilterLogEvents"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "ApiGatewayRole": {
      "Type": "AWS::IAM::Role",
      "Metadata": {
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      },
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": ["apigateway.amazonaws.com"]},
              "Action": ["sts:AssumeRole"]
            }
          ]
        }
      }
    },
    "ESProxyCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
        "BuildDate": "2026-06-09T15:56:38.763Z"
      }
    },
    "UtteranceLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-UtteranceLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "UtteranceLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {
              "Fn::Join": [
                "",
                ["https://", {"Fn::GetAtt": ["ESVar", "ESAddress"]}]
              ]
            },
            "UTTERANCE_BUCKET": {"Ref": "AssetBucket"},
            "UTTERANCE_KEY": "default-utterances.json",
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.utterances",
        "LoggingConfig": {"LogGroup": {"Ref": "UtteranceLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ESQidLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESQidLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESQidLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.qid",
        "LoggingConfig": {"LogGroup": {"Ref": "ESQidLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ESCleaningLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESCleaningLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESCleaningLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "FEEDBACK_DELETE_RANGE_MINUTES": {
              "Ref": "OpenSearchDashboardsRetentionMinutes"
            },
            "METRICS_DELETE_RANGE_MINUTES": {
              "Ref": "OpenSearchDashboardsRetentionMinutes"
            },
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.cleanmetrics",
        "LoggingConfig": {"LogGroup": {"Ref": "ESCleaningLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ScheduledESCleaning": {
      "Type": "AWS::Events::Rule",
      "Properties": {
        "Description": "",
        "ScheduleExpression": "rate(1 day)",
        "State": "ENABLED",
        "Targets": [
          {
            "Arn": {"Fn::GetAtt": ["ESCleaningLambda", "Arn"]},
            "Id": "ES_Cleaning_Function"
          }
        ]
      }
    },
    "PermissionForEventsToInvokeLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "FunctionName": {"Ref": "ESCleaningLambda"},
        "Action": "lambda:InvokeFunction",
        "Principal": "events.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["ScheduledESCleaning", "Arn"]}
      }
    },
    "ESLoggingLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESLoggingLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESLoggingLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "FIREHOSE_NAME": {"Ref": "GeneralKinesisFirehose"},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.logging",
        "LoggingConfig": {"LogGroup": {"Ref": "ESLoggingLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESLoggingLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Logging"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ESQueryLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ESQueryLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESQueryLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Environment": {
          "Variables": {
            "Fn::If": [
              "BuildExamples",
              {
                "SETTINGS_TABLE": {"Ref": "SettingsTable"},
                "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
                "ExampleJSLambdaQuiz": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdaQuiz"]
                },
                "ExampleJSLambdahook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.ExampleJSLambdahook"]
                },
                "ExamplePYTHONLambdaBotBroker": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaBotBroker"
                  ]
                },
                "ExamplePYTHONLambdaConnectCallback": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaConnectCallback"
                  ]
                },
                "ExamplePYTHONLambdaFeedback": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaFeedback"
                  ]
                },
                "ExamplePYTHONLambdaNext": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaNext"
                  ]
                },
                "ExamplePYTHONLambdaPrevious": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdaPrevious"
                  ]
                },
                "ExamplePYTHONLambdahello": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.ExamplePYTHONLambdahello"
                  ]
                },
                "EXTCreateRecentTopicsResponse": {
                  "Fn::GetAtt": [
                    "ExamplesStack",
                    "Outputs.EXTCreateRecentTopicsResponse"
                  ]
                },
                "EXTCustomJSHook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
                },
                "EXTCustomPYHook": {
                  "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]
                },
                "SOLUTION_ID": "SO0189",
                "SOLUTION_VERSION": "v7.3.14"
              },
              {
                "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
                "SOLUTION_ID": "SO0189",
                "SOLUTION_VERSION": "v7.3.14"
              }
            ]
          }
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Handler": "index.query",
        "LoggingConfig": {"LogGroup": {"Ref": "ESQueryLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Query"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ESProxyLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {
                "Fn::Sub": "/aws/lambda/${AWS::StackName}-ESProxyLambdaLogGroup"
              },
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ESProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/proxy-es.zip"},
          "S3ObjectVersion": {"Ref": "ESProxyCodeVersion"}
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"},
          {"Ref": "EsProxyLambdaLayer"},
          {"Ref": "QnABotCommonLambdaLayer"}
        ],
        "Environment": {
          "Variables": {
            "ES_TYPE": {"Fn::GetAtt": ["Var", "QnAType"]},
            "ES_INDEX": {"Fn::GetAtt": ["Var", "QnaIndex"]},
            "ES_ADDRESS": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
            "SETTINGS_TABLE": {"Ref": "SettingsTable"},
            "EMBEDDINGS_API": {"Ref": "EmbeddingsApi"},
            "EMBEDDINGS_LAMBDA_ARN": {"Ref": "EmbeddingsLambdaArn"},
            "DEFAULT_SETTINGS_PARAM": {"Ref": "DefaultQnABotSettings"},
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "ESProxyLambdaLogGroup"}},
        "MemorySize": "1408",
        "Role": {"Fn::GetAtt": ["ESProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Service"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ESProxyEmbeddingsPolicyResources": {
      "Type": "Custom::ModelAccess",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "EmbeddingsBedrockModelId": {
          "Fn::If": [
            "EmbeddingsBedrock",
            {
              "Fn::FindInMap": [
                "BedrockDefaults",
                {"Ref": "EmbeddingsBedrockModelId"},
                "ModelID"
              ]
            },
            {"Ref": "AWS::NoValue"}
          ]
        }
      }
    },
    "ESProxyLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Action": [
                    "translate:TranslateText",
                    "translate:GetTerminology",
                    "translate:ListTerminologies",
                    "comprehend:DetectDominantLanguage",
                    "cloudwatch:GetMetricStatistics",
                    "cloudwatch:ListMetrics"
                  ],
                  "Effect": "Allow",
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "translateReadOnly"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyName": "ParamStorePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter", "ssm:GetParameters"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:",
                          {"Fn::Sub": "${AWS::Partition}:"},
                          "ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "DefaultUserPoolJwksUrl"}
                        ]
                      ]
                    }
                  ]
                }
              ]
            }
          },
          {
            "Fn::If": [
              "EmbeddingsEnable",
              {
                "PolicyName": "EmbeddingsPolicy",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Fn::If": [
                        "EmbeddingsLambdaArn",
                        {
                          "Effect": "Allow",
                          "Action": ["lambda:InvokeFunction"],
                          "Resource": [{"Ref": "EmbeddingsLambdaArn"}]
                        },
                        {"Ref": "AWS::NoValue"}
                      ]
                    },
                    {
                      "Fn::If": [
                        "EmbeddingsBedrock",
                        {
                          "Effect": "Allow",
                          "Action": ["bedrock:InvokeModel"],
                          "Resource": {
                            "Fn::GetAtt": [
                              "ESProxyEmbeddingsPolicyResources",
                              "modelArn"
                            ]
                          }
                        },
                        {"Ref": "AWS::NoValue"}
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          },
          {
            "PolicyName": "S3QNABucketReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject", "s3:ListBucket"],
                  "Resource": ["arn:aws:s3:::QNA*/*", "arn:aws:s3:::qna*/*"]
                }
              ]
            }
          },
          {
            "PolicyName": "SettingsTableReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["dynamodb:Scan"],
                  "Resource": [{"Fn::GetAtt": ["SettingsTable", "Arn"]}]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "QueryLambdaInvokePolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Fn::If": [
            "BuildExamples",
            {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    "arn:aws:lambda:*:*:function:qna*",
                    "arn:aws:lambda:*:*:function:QNA*",
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExampleJSLambdaQuiz"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExampleJSLambdahook"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaBotBroker"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaConnectCallback"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaFeedback"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaNext"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdaPrevious"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.ExamplePYTHONLambdahello"
                      ]
                    },
                    {
                      "Fn::GetAtt": [
                        "ExamplesStack",
                        "Outputs.EXTCreateRecentTopicsResponse"
                      ]
                    },
                    {
                      "Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomJSHook"]
                    },
                    {"Fn::GetAtt": ["ExamplesStack", "Outputs.EXTCustomPYHook"]}
                  ]
                }
              ]
            },
            {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    "arn:aws:lambda:*:*:function:qna*",
                    "arn:aws:lambda:*:*:function:QNA*"
                  ]
                }
              ]
            }
          ]
        },
        "Roles": [{"Ref": "ESProxyLambdaRole"}]
      }
    },
    "ESLoggingLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "LambdaGeneralKinesisFirehoseQNALambda",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:qna-*"
                        ]
                      ]
                    },
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:aws:lambda:",
                          {"Ref": "AWS::Region"},
                          ":",
                          {"Ref": "AWS::AccountId"},
                          ":function:QNA-*"
                        ]
                      ]
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["comprehend:DetectPiiEntities"],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["firehose:PutRecord", "firehose:PutRecordBatch"],
                  "Resource": [
                    {"Fn::GetAtt": ["GeneralKinesisFirehose", "Arn"]}
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "QueryPolicy": {
      "Type": "AWS::IAM::ManagedPolicy",
      "Properties": {
        "PolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": ["es:ESHttp*"],
              "Resource": [{"Fn::Sub": "${ESVar.ESArn}/*"}]
            },
            {
              "Effect": "Allow",
              "Action": ["kendra:Query", "kendra:Retrieve"],
              "Resource": [
                {
                  "Fn::Sub": "arn:aws:kendra:${AWS::Region}:${AWS::AccountId}:index/*"
                }
              ]
            },
            {
              "Effect": "Allow",
              "Action": ["s3:Get*"],
              "Resource": [{"Fn::Sub": "arn:aws:s3:::${AssetBucket}*"}]
            },
            {
              "Effect": "Allow",
              "Action": ["comprehend:DetectSyntax"],
              "Resource": ["*"]
            }
          ]
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F5",
              "reason": "This role policy is required to have * action in its policy"
            },
            {
              "id": "W13",
              "reason": "This IAM policy requires to have * resource"
            }
          ]
        }
      }
    },
    "LexProxyLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexProxyLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "LexProxyLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { LexModelBuildingService } = require('@aws-sdk/client-lex-model-building-service');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\nconst region = process.env.AWS_REGION;\nconst lex = new LexModelBuildingService(customSdkConfig('C001', { region }));\n\nexports.handler = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n    try {\n        const result = await lex[event.fnc](event.params);\n        console.log(`Response: ${JSON.stringify(result, null, 2)}`);\n        return result;\n    } catch (error) {\n        console.log(`Error: ${error}`);\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n"
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexProxyLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["LexProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [
          {"Ref": "AwsSdkLayerLambdaLayer"},
          {"Ref": "CommonModulesLambdaLayer"}
        ],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "LexStatusLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-LexStatusLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "LexStatusLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { LexModelsV2Client, DescribeBotCommand } = require('@aws-sdk/client-lex-models-v2');\nconst { S3Client, GetObjectCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\nconst region = process.env.AWS_REGION;\nconst s3 = new S3Client(customSdkConfig('C022', { region }));\nconst lexv2 = new LexModelsV2Client(customSdkConfig('C002', { region }));\n\n\nfunction getStatusResponse(response, build) {\n    const botStatus = (response.botStatus == 'Available') ? 'READY' : response.botStatus;\n\n    const statusResponse = {\n        lambdaArn: process.env.FULFILLMENT_FUNCTION_ARN,\n        lambdaRole: process.env.FULFILLMENT_FUNCTION_ROLE,\n        botversion: 'live',\n        lexV2botname: process.env.LEXV2_BOT_NAME || 'LEX V2 Bot not installed',\n        lexV2botid: process.env.LEXV2_BOT_ID || 'LEX V2 Bot not installed',\n        lexV2botalias: process.env.LEXV2_BOT_ALIAS || 'LEX V2 Bot not installed',\n        lexV2botaliasid: process.env.LEXV2_BOT_ALIAS_ID || 'LEX V2 Bot not installed',\n        lexV2intent: process.env.LEXV2_INTENT || 'LEX V2 Bot not installed',\n        lexV2intentFallback: process.env.LEXV2_INTENT_FALLBACK || 'LEX V2 Bot not installed',\n        lexV2localeids: process.env.LEXV2_BOT_LOCALE_IDS || 'LEX V2 Bot not installed',\n        status: botStatus,\n        build,\n    };\n    return statusResponse;\n}\n\nexports.handler = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    const bucket = process.env.STATUS_BUCKET;\n    const lexV2StatusFile = process.env.LEXV2_STATUS_KEY;\n    let build = { status: 'READY', token: 'token' };\n    let response;\n\n    try {\n        const getObjCmd = new GetObjectCommand({ Bucket: bucket, Key: lexV2StatusFile });\n        response = await s3.send(getObjCmd);\n        const readableStreamV2 = Buffer.concat(await response.Body.toArray());\n        build = JSON.parse(readableStreamV2);\n    } catch (e) {\n        console.log('Unable to read S3 lex bot status file - perhaps it doesn\\'t yet exist. Returning READY');\n    }\n\n    const describeBotCmd = new DescribeBotCommand({\n        botId: process.env.LEXV2_BOT_ID,\n    });\n    response = await lexv2.send(describeBotCmd);\n    const statusResponse = getStatusResponse(response, build);\n    return statusResponse;\n};\n"
        },
        "Environment": {
          "Variables": {
            "STATUS_BUCKET": {"Ref": "BuildStatusBucket"},
            "LEXV2_STATUS_KEY": "lexV2status.json",
            "FULFILLMENT_FUNCTION_ARN": {
              "Fn::Join": [
                ":",
                [{"Fn::GetAtt": ["FulfillmentLambda", "Arn"]}, "live"]
              ]
            },
            "FULFILLMENT_FUNCTION_ROLE": {"Ref": "FulfillmentLambdaRole"},
            "LEXV2_BOT_NAME": {"Fn::GetAtt": ["LexV2Bot", "botName"]},
            "LEXV2_BOT_ID": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
            "LEXV2_BOT_ALIAS": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]},
            "LEXV2_BOT_ALIAS_ID": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
            "LEXV2_INTENT": {"Fn::GetAtt": ["LexV2Bot", "botIntent"]},
            "LEXV2_INTENT_FALLBACK": {
              "Fn::GetAtt": ["LexV2Bot", "botIntentFallback"]
            },
            "LEXV2_BOT_LOCALE_IDS": {
              "Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]
            },
            "SOLUTION_ID": "SO0189",
            "SOLUTION_VERSION": "v7.3.14"
          }
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "LexStatusLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["LexProxyLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "LexProxyLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyName": "AWSQnaBotLexFullAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "polly:SynthesizeSpeech",
                    "logs:DescribeLogGroups",
                    "cloudwatch:DescribeAlarms",
                    "kms:DescribeKey",
                    "s3:GetBucketLocation",
                    "lambda:GetPolicy"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:kms:${AWS::Region}:${AWS::AccountId}:key/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:polly:${AWS::Region}:${AWS::AccountId}:lexicon/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:cloudwatch:${AWS::Region}:${AWS::AccountId}:alarm:*"
                    },
                    {"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListAllMyBuckets",
                    "lambda:ListFunctions",
                    "cloudwatch:DescribeAlarmsForMetric",
                    "kms:ListAliases",
                    "iam:ListRoles",
                    "cloudwatch:GetMetricStatistics",
                    "kendra:ListIndices",
                    "polly:DescribeVoices"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:intent:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:slottype:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot:*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-channel:*:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:CreateUploadUrl",
                    "lex:ListBuiltInSlotTypes",
                    "lex:ListBots",
                    "lex:ListBuiltInIntents",
                    "lex:ListImports",
                    "lex:ListExports"
                  ],
                  "Resource": "*"
                },
                {
                  "Effect": "Allow",
                  "Action": "lex:*",
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot-alias/*/*"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lex:${AWS::Region}:${AWS::AccountId}:bot/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": {
                    "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:AmazonLex*"
                  },
                  "Condition": {
                    "StringEquals": {"lambda:Principal": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:GetRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {"iam:AWSServiceName": "lex.amazonaws.com"}
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lex.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:CreateServiceLinkedRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:AWSServiceName": "channels.lexv2.amazonaws.com"
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                  ],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots",
                    "arn:aws:iam::*:role/aws-service-role/channels.lex.amazonaws.com/AWSServiceRoleForLexChannels",
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*",
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lex.amazonaws.com/AWSServiceRoleForLexBots"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lex.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/lexv2.amazonaws.com/AWSServiceRoleForLexV2Bots*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["lexv2.amazonaws.com"]
                    }
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": [
                    "arn:aws:iam::*:role/aws-service-role/channels.lexv2.amazonaws.com/AWSServiceRoleForLexV2Channels*"
                  ],
                  "Condition": {
                    "StringEquals": {
                      "iam:PassedToService": ["channels.lexv2.amazonaws.com"]
                    }
                  }
                }
              ]
            }
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "Access",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:Get*"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${BuildStatusBucket}*"}
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            },
            {"id": "W76", "reason": "This role is required to have high SPCM"},
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "OpenSearchDashboardsRole": {
      "Type": "AWS::IAM::Role",
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "IAM_NO_INLINE_POLICY_CHECK",
            "CFN_NO_EXPLICIT_RESOURCE_NAMES"
          ]
        }
      },
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {
                    "Ref": "OpenSearchDashboardsIdPool"
                  }
                }
              }
            }
          ]
        },
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Fn::Select": [
                  "0",
                  {
                    "Fn::Split": [
                      "-",
                      {
                        "Fn::Select": [
                          2,
                          {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                        ]
                      }
                    ]
                  }
                ]
              },
              "-OpenSearchDashboardsRole"
            ]
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "OpenSearchDashboardsAccessPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Sid": "CognitoAuth",
                  "Effect": "Allow",
                  "Action": "es:ESHttp*",
                  "Resource": {"Fn::Sub": "${ESVar.ESArn}/*"}
                }
              ]
            }
          }
        ]
      }
    },
    "AdminRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                },
                "ForAnyValue:StringLike": {
                  "cognito-identity.amazonaws.com:amr": "authenticated"
                }
              }
            }
          ]
        },
        "Path": "/",
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Fn::Select": [
                  "0",
                  {
                    "Fn::Split": [
                      "-",
                      {
                        "Fn::Select": [
                          2,
                          {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                        ]
                      }
                    ]
                  }
                ]
              },
              "-AdminRole"
            ]
          ]
        },
        "Policies": [
          {
            "PolicyName": "apiAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["es:ESHttp*"],
                  "Resource": [{"Fn::GetAtt": ["ESVar", "ESArn"]}]
                },
                {
                  "Effect": "Allow",
                  "Action": ["cognito-idp:AdminUserGlobalSignOut"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${UserPool}"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["execute-api:*"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${API}/*/*/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:PutObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/data/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/data/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/data/*"},
                    {
                      "Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/data-testall/*"
                    },
                    {
                      "Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/data-export/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:InvokeFunction"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:${SolutionHelper}"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "dynamodb:GetItem",
                    "dynamodb:PutItem",
                    "dynamodb:Scan",
                    "dynamodb:UpdateItem",
                    "dynamodb:DeleteItem"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${SettingsTable}"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            }
          ]
        },
        "guard": {
          "SuppressedRules": [
            "IAM_NO_INLINE_POLICY_CHECK",
            "CFN_NO_EXPLICIT_RESOURCE_NAMES"
          ]
        }
      }
    },
    "UserRole": {
      "Type": "AWS::IAM::Role",
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "IAM_NO_INLINE_POLICY_CHECK",
            "CFN_NO_EXPLICIT_RESOURCE_NAMES"
          ]
        }
      },
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                },
                "ForAnyValue:StringLike": {
                  "cognito-identity.amazonaws.com:amr": "authenticated"
                }
              }
            }
          ]
        },
        "Path": "/",
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Fn::Select": [
                  "0",
                  {
                    "Fn::Split": [
                      "-",
                      {
                        "Fn::Select": [
                          2,
                          {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                        ]
                      }
                    ]
                  }
                ]
              },
              "-UserRole"
            ]
          ]
        },
        "Policies": [
          {
            "Fn::If": [
              "StreamingEnabled",
              {
                "PolicyName": "StreamingApiAccess",
                "PolicyDocument": {
                  "Version": "2012-10-17",
                  "Statement": [
                    {
                      "Effect": "Allow",
                      "Action": ["execute-api:Invoke"],
                      "Resource": [
                        {
                          "Fn::Join": [
                            "",
                            [
                              "arn:",
                              {"Fn::Sub": "${AWS::Partition}"},
                              ":execute-api:",
                              {"Fn::Sub": "${AWS::Region}"},
                              ":",
                              {"Fn::Sub": "${AWS::AccountId}"},
                              ":",
                              {
                                "Fn::GetAtt": [
                                  "StreamingStack",
                                  "Outputs.StreamingWebSocketApiId"
                                ]
                              },
                              "/Prod/*"
                            ]
                          ]
                        }
                      ]
                    }
                  ]
                }
              },
              {"Ref": "AWS::NoValue"}
            ]
          }
        ]
      }
    },
    "UnauthenticatedRole": {
      "Type": "AWS::IAM::Role",
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "IAM_NO_INLINE_POLICY_CHECK",
            "CFN_NO_EXPLICIT_RESOURCE_NAMES"
          ]
        }
      },
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Federated": "cognito-identity.amazonaws.com"},
              "Action": "sts:AssumeRoleWithWebIdentity",
              "Condition": {
                "StringEquals": {
                  "cognito-identity.amazonaws.com:aud": {"Ref": "IdPool"}
                },
                "ForAnyValue:StringLike": {
                  "cognito-identity.amazonaws.com:amr": "unauthenticated"
                }
              }
            }
          ]
        },
        "Path": "/",
        "RoleName": {
          "Fn::Join": [
            "",
            [
              {
                "Fn::Select": [
                  "0",
                  {
                    "Fn::Split": [
                      "-",
                      {
                        "Fn::Select": [
                          2,
                          {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                        ]
                      }
                    ]
                  }
                ]
              },
              "-UnauthenticatedRole"
            ]
          ]
        }
      }
    },
    "CFNLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "ManagedPolicyArns": [
          "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
          "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",
          "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
        ],
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyName": "CFNAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "es:ESHttp*",
                    "es:UpdateDomainConfig",
                    "es:DescribeDomain",
                    "es:DescribeDomains",
                    "es:DescribeDomainConfig"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:es:${AWS::Region}:${AWS::AccountId}:domain*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "lex:PutSlotType",
                    "lex:GetSlotType",
                    "lex:DeleteSlotType",
                    "lex:PutIntent",
                    "lex:GetIntent",
                    "lex:DeleteIntent",
                    "lex:PutBot",
                    "lex:GetBot",
                    "lex:DeleteBot",
                    "lex:PutBotAlias",
                    "lex:DeleteBotAlias",
                    "lex:GetBotAlias",
                    "lex:GetBotVersions",
                    "lex:GetIntentVersions",
                    "lex:GetSlotTypeVersions"
                  ],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["apigateway:*"],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "bedrock:GetInferenceProfile",
                    "bedrock:GetFoundationModel"
                  ],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["iam:PassRole"],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":iam::",
                        {"Ref": "AWS::AccountId"},
                        ":role/",
                        {
                          "Fn::Select": [
                            "0",
                            {
                              "Fn::Split": [
                                "-",
                                {
                                  "Fn::Select": [
                                    2,
                                    {
                                      "Fn::Split": [
                                        "/",
                                        {"Ref": "AWS::StackId"}
                                      ]
                                    }
                                  ]
                                }
                              ]
                            }
                          ]
                        },
                        "-*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "cognito-identity:SetIdentityPoolRoles",
                    "cognito-identity:GetIdentityPoolRoles",
                    "iam:CreateServiceLinkedRole"
                  ],
                  "Resource": ["*"]
                },
                {
                  "Effect": "Allow",
                  "Action": ["cognito-idp:*"],
                  "Resource": ["*"]
                },
                {
                  "Sid": "CFNLambdaS3Access",
                  "Effect": "Allow",
                  "Action": [
                    "s3:ListBucketVersions",
                    "s3:PutBucketNotification",
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:DeleteObjectVersion",
                    "s3:DeleteObject",
                    "s3:GetObjectVersion",
                    "s3:ListBucket"
                  ],
                  "Resource": [{"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}]
                },
                {
                  "Effect": "Allow",
                  "Action": ["lambda:PublishVersion"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    }
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "LambdaFunctionCustomResourcePollingPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["lambda:AddPermission", "lambda:RemovePermission"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "events:PutRule",
                    "events:DeleteRule",
                    "events:PutTargets",
                    "events:RemoveTargets"
                  ],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:events:${AWS::Region}:${AWS::AccountId}:rule/*"
                    }
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:PutBucketVersioning"],
                  "Resource": [{"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}]
                }
              ]
            }
          },
          {
            "PolicyName": "SettingsInitializerCustomResourcePolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "dynamodb:PutItem",
                    "dynamodb:Scan",
                    "dynamodb:GetItem",
                    "dynamodb:UpdateItem"
                  ],
                  "Resource": [{"Fn::GetAtt": ["SettingsTable", "Arn"]}]
                },
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${CustomQnABotSettings}"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${PrivateQnABotSettings}"
                    },
                    {
                      "Fn::Sub": "arn:${AWS::Partition}:ssm:${AWS::Region}:${AWS::AccountId}:parameter/${DefaultQnABotSettings}"
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "F3",
              "reason": "This role policy is required to have * action in its policy"
            },
            {
              "id": "F38",
              "reason": "This role policy is required to have * action in its policy with PassRole action"
            },
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "Bot": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "bot",
        "RestApiId": {"Ref": "API"}
      }
    },
    "AlexaApi": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Bot"},
        "PathPart": "alexa",
        "RestApiId": {"Ref": "API"}
      }
    },
    "AlexaSchema": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["UtteranceLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($utterances = $inputRoot.utterances)\n\n{\n  \"interactionModel\": {\n    \"languageModel\": {\n      \"invocationName\": \"q and a\",\n      \"types\": [\n        {\n          \"name\": \"EXAMPLE_QUESTIONS\",\n          \"values\": [\n            #foreach( $utterance in $utterances)\n                {\"name\":{\n                    \"value\":\"$utterance\" \n                }}#if( $foreach.hasNext ),#end\n            #end\n          ]\n        }\n        ## {\n        ##     \"name\": \"EXAMPLE_QUESTIONS\",\n        ##     \"values\": [\n        ##         {\n        ##             \"name\": {\n        ##                 \"value\": \"this is required\"\n        ##             }\n        ##         }\n        ##     ]\n        ##   }\n      ],\n      \"intents\": [\n        {\n          \"slots\": [\n            {\n              \"name\": \"QnA_slot\",\n              \"type\": \"EXAMPLE_QUESTIONS\"\n            }\n          ],\n          \"name\": \"Qna_intent\",\n          \"samples\": [\n            \"{QnA_slot}\"\n          ]\n        },\n        {\n          \"name\": \"AMAZON.StopIntent\"\n        },\n        {\n          \"name\": \"AMAZON.RepeatIntent\"\n        },\n        {\n          \"name\": \"AMAZON.FallbackIntent\"\n        },\n        {\n          \"name\": \"AMAZON.CancelIntent\"\n        }\n      ]\n    }\n  }\n}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n}                \n               \n\n"
            }
          }
        },
        "ResourceId": {"Ref": "AlexaApi"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotPost": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "POST",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["LexBuildLambdaStart", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\"token\":\"$input.path('$.token')\"}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ]
        },
        "ResourceId": {"Ref": "Bot"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["LexStatusLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n#set($inputRoot = $input.path('$'))\n\n{\n    \"lambdaArn\": \"$inputRoot.lambdaArn\",\n    \"lambdaRole\":\"$inputRoot.lambdaRole\",\n    \"botversion\":\"$inputRoot.botversion\",\n    \"botname\":\"$inputRoot.botname\",\n    \"intent\":\"$inputRoot.intent\",\n    \"intentFallback\":\"$inputRoot.intentFallback\",\n    \"lexV2botname\":\"$inputRoot.lexV2botname\",\n    \"lexV2botid\":\"$inputRoot.lexV2botid\",\n    \"lexV2botalias\":\"$inputRoot.lexV2botalias\",\n    \"lexV2botaliasid\":\"$inputRoot.lexV2botaliasid\",\n    \"lexV2intent\":\"$inputRoot.lexV2intent\",\n    \"lexV2intentFallback\":\"$inputRoot.lexV2intentFallback\",\n    \"lexV2localeids\":\"$inputRoot.lexV2localeids\",\n    \"status\":\"$inputRoot.status\",\n    \"build\":$input.json('$.build'),\n    \"_links\":{\n        \"alexa\":{\n            \"href\":\"$root/bot/alexa\"\n        }\n    }\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"fnc\":\"getBot\"\n}                \n               \n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Bot"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "BotDoc": {
      "Type": "AWS::ApiGateway::DocumentationPart",
      "Properties": {
        "Location": {"Type": "RESOURCE", "Path": "/bot"},
        "Properties": "{\"description\":\"\"}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "Health": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "health",
        "RestApiId": {"Ref": "API"}
      }
    },
    "HealthGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {"Fn::Sub": "{\"status\":\"health\"}\n\n"}
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"GET\",\n    \"path\":\"/_cluster/health\"\n}\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Health"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "rootGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"region\":\"${!stageVariables.Region}\",\n    \"Version\":\"${InfoVar.Version}\",\n    \"BuildDate\":\"${InfoVar.BuildDateString}\",\n    \"BotName\":\"Use LexV2 bot\",\n    \"BotVersion\":\"$LATEST\",\n    \"v2BotId\": \"${LexV2Bot.botId}\",\n    \"v2BotAliasId\": \"${LexV2Bot.botAliasId}\",\n    \"v2BotLocaleId\": \"${LexV2BotLocaleIds}\",\n    \"PoolId\":\"${IdPool}\",\n    \"StackName\":\"${AWS::StackName}\",\n    \"ClientIdClient\":\"${ClientClient}\",\n    \"ClientIdDesigner\":\"${ClientDesigner}\",\n    \"UserPool\":\"${UserPool}\",\n    \"StreamingWebSocketEndpoint\": \"$stageVariables.StreamingWebSocketEndpoint\",\n    \"SolutionHelper\": \"${SolutionHelper}\",\n    \"SettingsTable\": \"${SettingsTable}\",\n    \"Id\":\"$stageVariables.Id\",\n    \"_links\":{\n        \"root\":{\n            \"href\":\"$root\"\n        },\n        \"questions\":{\n            \"href\":\"$root/questions\"\n        },        \n        \"crawler\":{\n            \"href\":\"$root/crawler\"\n        },\n        \"crawlerV2\":{\n            \"href\":\"$root/kendranativecrawler\"\n        },\n        \"bot\":{\n            \"href\":\"$root/bot\"\n        },\n        \"jobs\":{\n            \"href\":\"$root/jobs\"\n        },\n        \"connect\":{\n            \"href\":\"$root/connect\"\n        },\n        \"genesys\":{\n            \"href\":\"$root/genesys\"\n        },\n        \"translate\":{\n            \"href\":\"$root/translate\"\n        },\n        \"examples\":{\n            \"href\":\"$root/examples/documents\"\n        },\n        \"DesignerLogin\":{\n            \"href\":\"$stageVariables.DesignerLoginUrl\"\n        },\n        \"ClientLogin\":{\n            \"href\":\"$stageVariables.ClientLoginUrl\"\n        },\n        \"CognitoEndpoint\":{\n            \"href\":\"$stageVariables.CognitoEndpoint\"\n        },\n        \"Services\":{\n            \"href\":\"$root/services\"\n        },\n        \"OpenSearchDashboards\":{\n            \"href\":\"https://${Urls.OpenSearchDashboards}\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Questions": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "questions",
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"total\":$inputRoot.hits.total.value,\n    \"version\":\"1\",\n    \"qa\":[\n        #foreach( $hit in $inputRoot.hits.hits)\n            {\n                #set($Scorepath =  '$.hits.hits['+$foreach.index+']._score')\n                \"_score\":$input.json($Scorepath),\n                #set($Bodypath =  '$.hits.hits['+$foreach.index+']._source')\n                #foreach($paramName in $input.path($Bodypath).keySet())\n                    #if( $paramName == 'questions')\n                        \"q\":[\n                            #foreach( $question in $input.path($Bodypath).get($paramName))\n                                \"$question.q\"\n                                #if($foreach.hasNext),#end\n                            #end\n                        ]\n                    #else\n                        #set( $body =  $Bodypath+\".\"+$paramName)\n                        \"$paramName\" :$input.json($body) \n                    #end\n                #if($foreach.hasNext),#end\n                #end\n            }#if( $foreach.hasNext ),#end\n        #end\n    ]\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#if ( $input.params('perpage').length()==0 )\n    #set ( $perpage = 10 )\n#else\n    #set ( $perpage = $input.params('perpage') )\n#end\n\n#if ( $input.params('from').length()==0)\n    #set ( $from = 0 )\n#else\n    #set ( $from = $input.params('from') )\n#end\n\n#if ( $input.params('order').length()==0 )\n    #set ( $order = \"asc\" )\n#else\n    #set ( $order = $input.params('order') )\n#end\n    \n{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n\n    \n    #if($input.params('query').length()>0)\n    \"path\":\"/${Var.QnaIndex}/_search?search_type=dfs_query_then_fetch\",\n    \"question\": \"$util.urlDecode($input.params('query'))\",\n    #else\n    \"path\":\"/${Var.QnaIndex}/_search?search_type=dfs_query_then_fetch\",\n    \"question\": \"\",\n    #end\n    \n    #if ($input.params('topic'))\n    \"topic\": \"$util.urlDecode($input.params('topic'))\",\n    #else\n    \"topic\": \"\",\n    #end\n\n    #if ($input.params('client_filter'))\n    \"client_filter\": \"$util.urlDecode($input.params('client_filter'))\",\n    #else\n    \"client_filter\": \"\",\n    #end\n\n    #if ($input.params('score_answer'))\n    \"score_answer\": \"$util.urlDecode($input.params('score_answer'))\",\n    #else\n    \"score_answer\": \"\",\n    #end\n\n    #if ($input.params('score_text_passage'))\n    \"score_text_passage\": \"$util.urlDecode($input.params('score_text_passage'))\",\n    #else\n    \"score_text_passage\": \"\",\n    #end\n\n    \"size\":\"$perpage\",\n    \"from\":\"$from\",\n\n\n    \"body\":{\n        #if($input.params('query').length()>0)\n        \"comment\": \"ES Query for test queries are now built dynamically by ESProxy Lambda handler.\"\n        #else\n        \"size\":\"$perpage\",\n        \"from\":\"$from\",\n        \"_source\": {\n            \"exclude\": [\"questions.q_vector\", \"a_vector\"]\n        },\n        \"query\": {\n            \"bool\":{\n                #if($input.params('filter').length()==0)\n                \"must\":{\"match_all\":{}}\n                #else\n                \"filter\":{\"regexp\":{\n                    \"qid\":\"$util.urlDecode($input.params('filter'))\"\n                }}\n                #end\n            }\n        }\n        ,\"sort\":{\n            \"qid\":{\n                \"order\":\"$order\" \n            }\n        }\n        #end\n    }\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.query": false,
          "method.request.querystring.topic": false,
          "method.request.querystring.from": false,
          "method.request.querystring.filter": false,
          "method.request.querystring.order": false,
          "method.request.querystring.perpage": false
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 204,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\n    \"message\":\"success\",\n    \"count\":\"$input.path('$.deleted')\"\n}\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n    \"path\":\"/${Var.QnaIndex}/_delete_by_query?refresh=true\",\n    \"body\":{\n        \"query\":{\n            #if($input.path('$.query').length()!=0)\n            \"bool\":{\n                \"must\":{\"match_all\":{}},\n                \"filter\":{\"regexp\":{\n                    \"qid\":\"$input.path('$.query')\"\n                }}\n            }\n            #else\n            \"terms\":{\n                \"qid\":[\n                #foreach($qid in $input.path('$.list'))\n                    \"$qid\"#if($foreach.hasNext),#end\n                #end]\n            }\n            #end\n        }\n    }\n}\n\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 204,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Question": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Questions"},
        "PathPart": "{ID}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseTemplates": {
                "application/json": {"Fn::Sub": "{\"status\":\"exists\"}\n"}
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"HEAD\",\n    \"path\":\"/${Var.QnaIndex}/_all/$util.urlDecode($input.params('ID'))\"\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 201,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($Idpath =  '$._id')\n#set($Successpath =  '$._shards.successful')\n\n{\n    \"result\":\"$inputRoot.result\",\n    \"id\":$input.json($Idpath),\n    \"success\":$input.json($Successpath)\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n#if($input.json('$.type').length())\n    #set($type=$inputRoot.type)\n#else\n    #set($type=\"qna\")\n#end\n\n{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"PUT\",\n    \"path\":\"/${Var.QnaIndex}/_doc/$input.params('ID')?refresh=wait_for\",\n    \"body\":{\n        #foreach($paramName in $inputRoot.keySet())\n            #if( $paramName == 'q' && $type==\"qna\")\n                ## generate quniqueterms field by concatenating questions in q array\n                \"quniqueterms\":\" #foreach( $q in $inputRoot.get($paramName))$q #end \",\n                ## replace q array with nested questions array\n                \"questions\":[\n                    #foreach( $q in $inputRoot.get($paramName))\n                        {\"q\":\"$q\"}\n                        #if($foreach.hasNext),#end\n                    #end\n                ]\n                #if($foreach.hasNext),#end\n            #else\n                #set( $body =  '$.'+$paramName)\n                \"$paramName\" :$input.json($body) \n                #if($foreach.hasNext),#end\n            #end\n        #end\n    }\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 201,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionsOptions": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "OPTIONS",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["SchemaLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"comment\": \"API mapping no-op since ES 7.x upgrade. Schema now returned directly from SchemaLambda, rather than from OpenSearch metadata\"\n}\n\n"
            }
          }
        },
        "ResourceId": {"Ref": "Questions"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "QuestionDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {
              "StatusCode": 204,
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set($inputRoot = $input.path('$'))\n#set($Idpath =  '$._id')\n#set($Successpath =  '$._shards.successful')\n\n{\n    \"result\":\"$inputRoot.result\",\n    \"id\":$input.json($Idpath),\n    \"success\":$input.json($Successpath)\n}\n\n"
                }
              }
            },
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "{\n    \"endpoint\":\"${ESVar.ESAddress}\",\n    \"method\":\"POST\",\n    \"path\":\"/${Var.QnaIndex}/_delete_by_query?refresh=true\",\n    \"body\":{\n        \"query\":{\n            \"match\":{\n                \"qid\":\"$util.urlDecode($input.params('ID'))\"\n            }\n        }\n    }\n\n}\n\n\n"
            }
          }
        },
        "RequestParameters": {"method.request.path.Id": true},
        "ResourceId": {"Ref": "Question"},
        "MethodResponses": [
          {
            "StatusCode": 204,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Static": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "static",
        "RestApiId": {"Ref": "API"}
      }
    },
    "Proxy": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Static"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ProxyAnyGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Proxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "ProxyAnyHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "HEAD",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Proxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Fonts": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Static"},
        "PathPart": "fonts",
        "RestApiId": {"Ref": "API"}
      }
    },
    "FontsProxy": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Fonts"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "FontsProxyGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/fonts/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ContentHandling": "CONVERT_TO_BINARY",
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "FontsProxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Login": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "pages",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DesignerLoginResource": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Login"},
        "PathPart": "designer",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ClientLoginResource": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Login"},
        "PathPart": "client",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DesignerLoginResourceGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseParameters": {
                "method.response.header.location": {
                  "Fn::Join": [
                    "",
                    ["'", {"Fn::GetAtt": ["DesignerLogin", "loginUrl"]}, "'"]
                  ]
                }
              },
              "StatusCode": "302"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 302}"}
        },
        "ResourceId": {"Ref": "DesignerLoginResource"},
        "MethodResponses": [
          {
            "StatusCode": 302,
            "ResponseParameters": {"method.response.header.location": true}
          }
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "ClientLoginResourceGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseParameters": {
                "method.response.header.location": {
                  "Fn::Join": [
                    "",
                    ["'", {"Fn::GetAtt": ["ClientLogin", "loginUrl"]}, "'"]
                  ]
                }
              },
              "StatusCode": "302"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 302}"}
        },
        "ResourceId": {"Ref": "ClientLoginResource"},
        "MethodResponses": [
          {
            "StatusCode": 302,
            "ResponseParameters": {"method.response.header.location": true}
          }
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Jobs": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "jobs",
        "RestApiId": {"Ref": "API"}
      }
    },
    "JobsGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"_links\":{\n        \"imports\":{\n            \"href\":\"$root/jobs/imports\",\n            \"bucket\":\"${ImportBucket}\",\n            \"uploadPrefix\":\"data/\",\n            \"statusPrefix\":\"Status/\"\n        },\n        \"exports\":{\n            \"href\":\"$root/jobs/exports\"\n        },\n        \"testall\":{\n            \"href\":\"$root/jobs/testall\",\n            \"bucket\":\"${TestAllBucket}\",\n            \"statusPrefix\":\"Status/\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Jobs"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "testalls": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "testall",
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${ContentDesignerOutputBucket}\",\n    \"prefix\":\"status-testall/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"testall\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "testalls"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testall": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "testalls"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "PUT",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "TestAllBucket"},
                "/status-testall/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"bucket\":\"${TestAllBucket}\",\n    \"index\":\"${Var.QnaIndex}\",\n    \"id\":\"$input.params('proxy')\",\n    \"config\":\"status-testall/$input.params('proxy')\",\n    \"tmp\":\"tmp-testall/$input.params('proxy')\",\n    \"key\":\"data-testall/$input.params('proxy')\",\n    \"filter\":\"$inputRoot.get('filter')\",\n    \"token\":\"$inputRoot.get('token')\",\n    \"locale\":\"$inputRoot.get('locale')\",\n    \"status\":\"Started\"\n}\n\n"
            }
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status-testall/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "testallDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status-testall/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "testall"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exports": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "exports",
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${ContentDesignerOutputBucket}\",\n    \"prefix\":\"status-export/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"exports\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "exports"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "export": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "exports"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "imports": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Jobs"},
        "PathPart": "imports",
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportPut": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "PUT",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "PUT",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ExportBucket"},
                "/status-export/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set($inputRoot = $input.path('$'))\n\n{\n    \"bucket\":\"${ExportBucket}\",\n    \"index\":\"${Var.QnaIndex}\",\n    \"id\":\"$input.params('proxy')\",\n    \"config\":\"status/$input.params('proxy')\",\n    \"tmp\":\"tmp/$input.params('proxy')\",\n    \"key\":\"$inputRoot.get('prefix')data-export/$input.params('proxy')\",\n    \"filter\":\"$inputRoot.get('filter')\",\n    \"status\":\"Started\"\n}"
            }
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status-export/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "exportDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "export"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "importsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${ContentDesignerOutputBucket}\",\n    \"prefix\":\"status-import/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"type\":\"imports\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "imports"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "import": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "imports"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "importGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status-import/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "import"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "importDelete": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "DELETE",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "DELETE",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "ContentDesignerOutputBucket"},
                "/status-import/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Job not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "import"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "S3ListLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-S3ListLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "S3ListLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { S3Client, ListObjectsCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\nconst region = process.env.AWS_REGION;\nconst s3 = new S3Client(customSdkConfig('C022', { region }));\n\nexports.handler = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        const result = await s3.send(new ListObjectsCommand({\n            Bucket: event.bucket,\n            Prefix: event.prefix,\n            MaxKeys: event.perpage || 100,\n            Marker: event.token || null,\n        }));\n        \n        console.log('s3 response for routes:', JSON.stringify(result, null, 2));\n        if (result.Contents) {\n            result.Contents?.sort((a, b) => {\n                if (a.LastModified && b.LastModified) {\n                    return new Date(b.LastModified).getTime() - new Date(a.LastModified).getTime();\n                }\n                return 0;\n            });\n        }\n        const mapJobs = result?.Contents?.map((y) => ({\n            id: y.Key.split('/').pop(),\n            href: `${event.root}/jobs/${event.type}/${encodeURI(y.Key.split('/').pop())}`,\n        }));\n        \n        return {\n            token: result.NextMarker,\n            jobs: result.Contents ? mapJobs : [],\n        };\n    } catch (error) {\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n"
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "S3ListLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "S3ListLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "S3ListPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["S3:List*"],
                  "Resource": [{"Fn::Sub": "arn:${AWS::Partition}:s3:::*"}]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "Examples": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "examples",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExamplesGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n\n{\n    \"_links\":{\n        \"documents\":{\n            \"href\":\"$root/examples/documents\"\n        },\n        \"photos\":{\n            \"href\":\"$root/examples/photos\"\n        }\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Examples"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "photos": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Examples"},
        "PathPart": "photos",
        "RestApiId": {"Ref": "API"}
      }
    },
    "photosList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ExampleS3ListPhotoLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${AssetBucket}\",\n    \"prefix\":\"examples/photos/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "photos"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "photo": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "photos"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "photoGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/photos/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "photo"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Documents": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Examples"},
        "PathPart": "documents",
        "RestApiId": {"Ref": "API"}
      }
    },
    "DocumentsList": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "POST",
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":lambda:path/2015-03-31/functions/",
                {"Fn::GetAtt": ["ExampleS3ListLambda", "Arn"]},
                "/invocations"
              ]
            ]
          },
          "IntegrationResponses": [
            {"StatusCode": 200},
            {
              "SelectionPattern": ".*[InternalServiceError].*",
              "StatusCode": 500,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[BadRequest].*",
              "StatusCode": 400,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[Conflict].*",
              "StatusCode": 409,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*[NotFound].*",
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            },
            {
              "SelectionPattern": ".*Exception.*",
              "StatusCode": 405,
              "ResponseTemplates": {
                "application/json": "#set ($errorMessageObj = $util.parseJson($input.path('$.errorMessage')))\n\n\n{\n    \"type\":\"$errorMessageObj.type\",\n    \"message\":\"$errorMessageObj.message\",\n    \"data\":\"$errorMessageObj.data\"\n}\n\n"
              }
            }
          ],
          "RequestTemplates": {
            "application/json": {
              "Fn::Sub": "#set ($root=\"https://${!context.domainName}/${!context.stage}\")\n\n{\n    \"bucket\":\"${AssetBucket}\",\n    \"prefix\":\"examples/documents/\",\n    \"perpage\":\"$input.params('perpage')\",\n    \"token\":\"$input.params('token')\",\n    \"root\":\"$root\"\n}\n\n"
            }
          }
        },
        "RequestParameters": {
          "method.request.querystring.perpage": false,
          "method.request.querystring.token": false
        },
        "ResourceId": {"Ref": "Documents"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.date": true}
          },
          {"StatusCode": 404},
          {"StatusCode": 405},
          {"StatusCode": 500}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "Example": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Documents"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/documents/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Example"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleHead": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "HEAD",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "HEAD",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "AssetBucket"},
                "/examples/documents/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not Found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "Example"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {"method.response.header.content-type": false}
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      }
    },
    "ExampleS3ListLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-ExampleS3ListLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ExampleS3ListLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { S3Client, ListObjectsCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\nconst region = process.env.AWS_REGION;\nconst s3 = new S3Client(customSdkConfig('C018', { region }));\n\nexports.photos = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        const result = await s3.send(new ListObjectsCommand({\n            Bucket: event.bucket,\n            Prefix: event.prefix,\n            MaxKeys: event.perpage || 100,\n            Marker: event.token || null,\n        }));\n        \n        console.log('s3 response for photos:', JSON.stringify(result, null, 2));\n        const photos = result?.Contents?.map((value) => {\n            const key = value.Key.split('/').pop();\n            return `${event.root}/examples/photos/${key}`;\n        }, []);\n        \n        return {\n            token: result.NextMarker,\n            photos,\n        };\n    } catch (error) {\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n\nexports.documents = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        const result = await s3.send(new ListObjectsCommand({\n            Bucket: event.bucket,\n            Prefix: event.prefix,\n            MaxKeys: event.perpage || 100,\n            Marker: event.token || null,\n        }));\n        \n        console.log('s3 response for documents:', JSON.stringify(result, null, 2));\n        const examples = result?.Contents?.reduce((accum, value) => {\n            let key = value.Key.split('/').pop().split('.');\n            const ext = key.length > 1 ? key.pop() : 'txt';\n            key = key[0];\n            const href = `${event.root}/examples/documents/${key}.${ext}`;\n            if (!accum[key]) {\n                accum[key] = { id: key };\n            }\n            if (ext === 'json') {\n                accum[key].document = { href };\n            } else {\n                accum[key].description = { href };\n            }\n            return accum;\n        }, {});\n\n        return {\n            token: result.NextMarker,\n            examples: examples ? Object.keys(examples).map((x) => examples[x]) : [],\n        };\n    } catch (error) {\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n"
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.documents",
        "LoggingConfig": {"LogGroup": {"Ref": "ExampleS3ListLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "ExampleS3ListPhotoLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {
                "Fn::Sub": "/aws/lambda/${AWS::StackName}-ExampleS3ListPhotoLambda"
              },
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "ExampleS3ListPhotoLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst { S3Client, ListObjectsCommand } = require('@aws-sdk/client-s3');\nconst customSdkConfig = require('sdk-config/customSdkConfig');\nconst region = process.env.AWS_REGION;\nconst s3 = new S3Client(customSdkConfig('C018', { region }));\n\nexports.photos = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        const result = await s3.send(new ListObjectsCommand({\n            Bucket: event.bucket,\n            Prefix: event.prefix,\n            MaxKeys: event.perpage || 100,\n            Marker: event.token || null,\n        }));\n        \n        console.log('s3 response for photos:', JSON.stringify(result, null, 2));\n        const photos = result?.Contents?.map((value) => {\n            const key = value.Key.split('/').pop();\n            return `${event.root}/examples/photos/${key}`;\n        }, []);\n        \n        return {\n            token: result.NextMarker,\n            photos,\n        };\n    } catch (error) {\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n\nexports.documents = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        const result = await s3.send(new ListObjectsCommand({\n            Bucket: event.bucket,\n            Prefix: event.prefix,\n            MaxKeys: event.perpage || 100,\n            Marker: event.token || null,\n        }));\n        \n        console.log('s3 response for documents:', JSON.stringify(result, null, 2));\n        const examples = result?.Contents?.reduce((accum, value) => {\n            let key = value.Key.split('/').pop().split('.');\n            const ext = key.length > 1 ? key.pop() : 'txt';\n            key = key[0];\n            const href = `${event.root}/examples/documents/${key}.${ext}`;\n            if (!accum[key]) {\n                accum[key] = { id: key };\n            }\n            if (ext === 'json') {\n                accum[key].document = { href };\n            } else {\n                accum[key].description = { href };\n            }\n            return accum;\n        }, {});\n\n        return {\n            token: result.NextMarker,\n            examples: examples ? Object.keys(examples).map((x) => examples[x]) : [],\n        };\n    } catch (error) {\n        throw JSON.stringify({\n            type: '[InternalServiceError]',\n            data: error,\n        });\n    }\n};\n"
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Handler": "index.photos",
        "LoggingConfig": {
          "LogGroup": {"Ref": "ExampleS3ListPhotoLambdaLogGroup"}
        },
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["S3ListLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "Services": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "services",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ServicesGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "AWS_IAM",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "MOCK",
          "IntegrationResponses": [
            {
              "ResponseTemplates": {
                "application/json": {
                  "Fn::Sub": "{\n    \"opensearch\":{\n        \"qid\":\"${ESQidLambda.Arn}\",\n        \"proxy\":\"${ESProxyLambda.Arn}\"\n    }\n}\n\n"
                }
              },
              "StatusCode": "200"
            }
          ],
          "RequestTemplates": {"application/json": "{\"statusCode\": 200}"}
        },
        "ResourceId": {"Ref": "Services"},
        "MethodResponses": [{"StatusCode": 200}],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Images": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Fn::GetAtt": ["API", "RootResourceId"]},
        "PathPart": "images",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ImagesProxy": {
      "Type": "AWS::ApiGateway::Resource",
      "Properties": {
        "ParentId": {"Ref": "Images"},
        "PathPart": "{proxy+}",
        "RestApiId": {"Ref": "API"}
      }
    },
    "ImagesProxyGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "AuthorizationType": "NONE",
        "HttpMethod": "GET",
        "Integration": {
          "Type": "AWS",
          "IntegrationHttpMethod": "GET",
          "Credentials": {"Fn::GetAtt": ["S3AccessRole", "Arn"]},
          "Uri": {
            "Fn::Join": [
              "",
              [
                "arn:aws:apigateway:",
                {"Ref": "AWS::Region"},
                ":s3:path/",
                {"Ref": "Bucket"},
                "/assets/{proxy}"
              ]
            ]
          },
          "RequestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
          },
          "IntegrationResponses": [
            {
              "StatusCode": 200,
              "ContentHandling": "CONVERT_TO_BINARY",
              "ResponseParameters": {
                "method.response.header.content-type": "integration.response.header.Content-Type",
                "method.response.header.api-stage": "context.stage"
              }
            },
            {
              "StatusCode": 404,
              "ResponseTemplates": {
                "application/xml": "{\"error\":\"Not found\"}"
              },
              "SelectionPattern": "403"
            }
          ]
        },
        "RequestParameters": {"method.request.path.proxy": false},
        "ResourceId": {"Ref": "ImagesProxy"},
        "MethodResponses": [
          {
            "StatusCode": 200,
            "ResponseParameters": {
              "method.response.header.content-type": false,
              "method.response.header.api-stage": false
            }
          },
          {"StatusCode": 400},
          {"StatusCode": 404}
        ],
        "RestApiId": {"Ref": "API"}
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W59",
              "reason": "This ApiGateway Method does not need authorization setup"
            }
          ]
        }
      }
    },
    "Bucket": {
      "Type": "AWS::S3::Bucket",
      "Metadata": {
        "guard": {"SuppressedRules": ["S3_BUCKET_NO_PUBLIC_RW_ACL"]}
      },
      "DependsOn": ["MainAccessLogBucket", "MainAccessLogsBucketPolicy"],
      "DeletionPolicy": "Delete",
      "Properties": {
        "VersioningConfiguration": {"Status": "Enabled"},
        "WebsiteConfiguration": {"IndexDocument": "index.html"},
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true,
          "IgnorePublicAcls": true,
          "RestrictPublicBuckets": true
        },
        "LoggingConfiguration": {
          "DestinationBucketName": {"Ref": "MainAccessLogBucket"},
          "LogFilePrefix": {
            "Fn::Join": ["", [{"Ref": "MainAccessLogBucket"}, "/S3Bucket/"]]
          }
        },
        "BucketEncryption": {
          "ServerSideEncryptionConfiguration": [
            {"ServerSideEncryptionByDefault": {"SSEAlgorithm": "AES256"}}
          ]
        }
      }
    },
    "HTTPSOnlyBucketPolicy": {
      "Type": "AWS::S3::BucketPolicy",
      "Properties": {
        "Bucket": {"Ref": "Bucket"},
        "PolicyDocument": {
          "Statement": [
            {
              "Action": "*",
              "Condition": {"Bool": {"aws:SecureTransport": "false"}},
              "Effect": "Deny",
              "Principal": "*",
              "Resource": [
                {"Fn::Join": ["", [{"Fn::GetAtt": ["Bucket", "Arn"]}, "/*"]]},
                {"Fn::Join": ["", [{"Fn::GetAtt": ["Bucket", "Arn"]}]]}
              ],
              "Sid": "HttpsOnly"
            }
          ],
          "Version": "2012-10-17"
        }
      }
    },
    "Clean": {
      "Type": "Custom::S3Clean",
      "DependsOn": ["CFNInvokePolicy", "HTTPSOnlyBucketPolicy"],
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["S3Clean", "Arn"]},
        "Bucket": {"Ref": "Bucket"}
      }
    },
    "Unzip": {
      "Type": "Custom::S3Unzip",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "SrcBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Join": ["", ["qnabot-on-aws/v7.3.14", "/website.zip"]]},
        "DstBucket": {"Ref": "Bucket"},
        "buildDate": "2026-06-09T15:56:38.764Z"
      },
      "DependsOn": "Clean"
    },
    "S3AccessRole": {
      "Type": "AWS::IAM::Role",
      "Metadata": {
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      },
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "apigateway.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyName": "S3AccessPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["s3:GetObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${Bucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${AssetBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:PutObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/*"}
                  ]
                },
                {
                  "Effect": "Allow",
                  "Action": ["s3:DeleteObject"],
                  "Resource": [
                    {"Fn::Sub": "arn:aws:s3:::${ImportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ExportBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${TestAllBucket}/*"},
                    {"Fn::Sub": "arn:aws:s3:::${ContentDesignerOutputBucket}/*"}
                  ]
                }
              ]
            }
          }
        ]
      }
    },
    "S3ClearCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/s3-clean.zip"},
        "BuildDate": "2026-06-09T15:56:38.765Z"
      }
    },
    "S3CleanLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-S3CleanLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "S3Clean": {
      "Type": "AWS::Lambda::Function",
      "Metadata": {
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      },
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/s3-clean.zip"}
        },
        "Environment": {
          "Variables": {"SOLUTION_ID": "SO0189", "SOLUTION_VERSION": "v7.3.14"}
        },
        "Description": "This function clears all S3 objects from the bucket of a given S3-based resource",
        "Handler": "lambda_function.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "S3CleanLambdaLogGroup"}},
        "Role": {"Fn::GetAtt": ["CFNLambdaRole", "Arn"]},
        "Runtime": "python3.14",
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "S3 Clean"}],
        "Timeout": 300
      }
    },
    "SchemaLambdaCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/schema.zip"},
        "BuildDate": "2026-06-09T15:56:38.765Z"
      }
    },
    "SchemaLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-SchemaLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "SchemaLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/schema.zip"},
          "S3ObjectVersion": {"Ref": "SchemaLambdaCodeVersion"}
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "SchemaLambdaLogGroup"}},
        "MemorySize": "128",
        "Role": {"Fn::GetAtt": ["SchemaLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Api"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "SchemaLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          }
        ],
        "ManagedPolicyArns": [{"Ref": "QueryPolicy"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "DefaultUserPoolJwksUrl": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Default QnABot Setting - DO NOT MODIFY",
        "Type": "String",
        "Value": {
          "Fn::Join": [
            "",
            [
              "https://cognito-idp.",
              {"Ref": "AWS::Region"},
              ".amazonaws.com/",
              {"Ref": "UserPool"},
              "/.well-known/jwks.json"
            ]
          ]
        }
      }
    },
    "DefaultQnABotSettings": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Default QnABot Settings - DO NOT MODIFY",
        "Type": "String",
        "Tier": "Advanced",
        "Value": {
          "Fn::Sub": [
            "{\"ENABLE_DEBUG_RESPONSES\":\"false\",\"ENABLE_DEBUG_LOGGING\":\"false\",\"ES_USE_KEYWORD_FILTERS\":\"${ES_USE_KEYWORD_FILTERS}\",\"ES_EXPAND_CONTRACTIONS\":\"{\\\"you're\\\":\\\"you are\\\",\\\"I'm\\\":\\\"I am\\\",\\\"can't\\\":\\\"cannot\\\"}\",\"ES_KEYWORD_SYNTAX_TYPES\":\"NOUN,PROPN,VERB,INTJ\",\"ES_SYNTAX_CONFIDENCE_LIMIT\":0.2,\"ES_MINIMUM_SHOULD_MATCH\":\"2<75%\",\"ES_NO_HITS_QUESTION\":\"no_hits\",\"ES_ERROR_QUESTION\":\"error_msg\",\"ES_USE_FUZZY_MATCH\":\"false\",\"ES_PHRASE_BOOST\":4,\"ES_SCORE_ANSWER_FIELD\":\"false\",\"ES_SCORE_TEXT_ITEM_PASSAGES\":\"true\",\"ENABLE_SENTIMENT_SUPPORT\":\"true\",\"ENABLE_MULTI_LANGUAGE_SUPPORT\":\"false\",\"ENABLE_CUSTOM_TERMINOLOGY\":\"false\",\"MINIMUM_CONFIDENCE_SCORE\":0.6,\"ALT_SEARCH_KENDRA_FALLBACK_CONFIDENCE_SCORE\":\"HIGH\",\"ALT_SEARCH_KENDRA_FAQ_CONFIDENCE_SCORE\":\"HIGH\",\"ALT_SEARCH_KENDRA_S3_SIGNED_URLS\":\"true\",\"ALT_SEARCH_KENDRA_S3_SIGNED_URL_EXPIRE_SECS\":300,\"ALT_SEARCH_KENDRA_MAX_DOCUMENT_COUNT\":2,\"ALT_SEARCH_KENDRA_TOP_ANSWER_MESSAGE\":\"Amazon Kendra suggested answer.\",\"ALT_SEARCH_KENDRA_FAQ_MESSAGE\":\"Answer from Amazon Kendra FAQ.\",\"ALT_SEARCH_KENDRA_ANSWER_MESSAGE\":\"While I did not find an exact answer, these search results from Amazon Kendra might be helpful.\",\"ALT_SEARCH_KENDRA_RESPONSE_TYPES\":\"ANSWER,DOCUMENT,QUESTION_ANSWER\",\"ALT_SEARCH_KENDRA_ABBREVIATE_MESSAGE_FOR_SSML\":\"true\",\"KENDRA_FAQ_CONFIG_MAX_RETRIES\":8,\"KENDRA_FAQ_CONFIG_RETRY_DELAY\":600,\"KENDRA_FAQ_ES_FALLBACK\":\"true\",\"ENABLE_KENDRA_WEB_INDEXER\":\"false\",\"KENDRA_INDEXER_URLS\":\"\",\"KENDRA_INDEXER_CRAWL_DEPTH\":3,\"KENDRA_INDEXER_CRAWL_MODE\":\"SUBDOMAINS\",\"KENDRA_INDEXER_SCHEDULE\":\"rate(1 day)\",\"KENDRA_INDEXED_DOCUMENTS_LANGUAGES\":\"en\",\"ERRORMESSAGE\":\"Unfortunately I encountered an error when searching for your answer. Please ask me again later.\",\"EMPTYMESSAGE\":\"You stumped me! Sadly I do not know how to answer your question.\",\"DEFAULT_ALEXA_LAUNCH_MESSAGE\":\"Hello, Please ask a question\",\"DEFAULT_ALEXA_REPROMPT\":\"Please either answer the question, ask another question or say Goodbye to end the conversation.\",\"DEFAULT_ALEXA_STOP_MESSAGE\":\"Goodbye\",\"SMS_HINT_REMINDER_ENABLE\":\"true\",\"SMS_HINT_REMINDER\":\" (Feedback? Reply THUMBS UP or THUMBS DOWN. Ask HELP ME at any time)\",\"SMS_HINT_REMINDER_INTERVAL_HRS\":24,\"IDENTITY_PROVIDER_JWKS_URLS\":[],\"ENFORCE_VERIFIED_IDENTITY\":\"false\",\"NO_VERIFIED_IDENTITY_QUESTION\":\"no_verified_identity\",\"ELICIT_RESPONSE_MAX_RETRIES\":3,\"ELICIT_RESPONSE_RETRY_MESSAGE\":\"Please try again.\",\"ELICIT_RESPONSE_BOT_FAILURE_MESSAGE\":\"Your response was not understood. Please start again.\",\"ELICIT_RESPONSE_DEFAULT_MSG\":\"Ok. \",\"CONNECT_IGNORE_WORDS\":\"\",\"CONNECT_ENABLE_VOICE_RESPONSE_INTERRUPT\":\"false\",\"CONNECT_NEXT_PROMPT_VARNAME\":\"connect_nextPrompt\",\"ENABLE_REDACTING\":\"false\",\"REDACTING_REGEX\":\"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b\",\"ENABLE_REDACTING_WITH_COMPREHEND\":\"false\",\"COMPREHEND_REDACTING_CONFIDENCE_SCORE\":0.99,\"COMPREHEND_REDACTING_ENTITY_TYPES\":\"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER\",\"PII_REJECTION_ENABLED\":false,\"PII_REJECTION_QUESTION\":\"pii_rejection_question\",\"PII_REJECTION_REGEX\":\"\\\\b\\\\d{4}\\\\b(?![-])|\\\\b\\\\d{9}\\\\b|\\\\b\\\\d{3}-\\\\d{2}-\\\\d{4}\\\\b\",\"PII_REJECTION_ENTITY_TYPES\":\"ADDRESS,EMAIL,SSN,PHONE,PASSWORD,BANK_ACCOUNT_NUMBER,BANK_ROUTING,CREDIT_DEBIT_NUMBER\",\"PII_REJECTION_CONFIDENCE_SCORE\":0.99,\"DISABLE_CLOUDWATCH_LOGGING\":\"false\",\"MINIMAL_ES_LOGGING\":\"false\",\"S3_PUT_REQUEST_ENCRYPTION\":\"\",\"BOT_ROUTER_WELCOME_BACK_MSG\":\"Welcome back to QnABot.\",\"BOT_ROUTER_EXIT_MSGS\":\"exit,quit,goodbye,leave\",\"RUN_LAMBDAHOOK_FROM_QUERY_STEP\":\"true\",\"LAMBDA_PREPROCESS_HOOK\":\"\",\"LAMBDA_POSTPROCESS_HOOK\":\"\",\"SEARCH_REPLACE_QUESTION_SUBSTRINGS\":\"\",\"PROTECTED_UTTERANCES\":\"help,help me,thumbs up,thumbs down,repeat,no_hits,no_verified_identity,reset language,detect language,english,french,spanish,german,italian,chinese,arabic,greek,repeat,can you repeat that,can you please say that again,please repeat that\",\"EMBEDDINGS_ENABLE\":\"${EMBEDDINGS_ENABLE}\",\"EMBEDDINGS_SCORE_THRESHOLD\":\"${EMBEDDINGS_SCORE_THRESHOLD}\",\"EMBEDDINGS_SCORE_ANSWER_THRESHOLD\":0.8,\"EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD\":\"${EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD}\",\"EMBEDDINGS_MAX_TOKEN_LIMIT\":\"${EMBEDDINGS_MAX_TOKEN_LIMIT}\",\"LLM_GENERATE_QUERY_ENABLE\":\"${LLM_GENERATE_QUERY_ENABLE}\",\"LLM_GENERATE_QUERY_PROMPT_TEMPLATE\":\"${LLM_GENERATE_QUERY_PROMPT_TEMPLATE}\",\"LLM_GENERATE_QUERY_MODEL_PARAMS\":\"${LLM_GENERATE_QUERY_MODEL_PARAMS}\",\"LLM_QA_ENABLE\":\"${LLM_QA_ENABLE}\",\"LLM_QA_USE_KENDRA_RETRIEVAL_API\":\"${LLM_QA_ENABLE}\",\"LLM_QA_PROMPT_TEMPLATE\":\"${LLM_QA_PROMPT_TEMPLATE}\",\"LLM_QA_MODEL_PARAMS\":\"${LLM_QA_MODEL_PARAMS}\",\"LLM_QA_PREFIX_MESSAGE\":\"LLM Answer:\",\"LLM_QA_SHOW_CONTEXT_TEXT\":\"true\",\"LLM_QA_SHOW_SOURCE_LINKS\":\"true\",\"LLM_CHAT_HISTORY_MAX_MESSAGES\":12,\"LLM_QA_NO_HITS_REGEX\":\"${LLM_QA_NO_HITS_REGEX}\",\"LLM_PROMPT_MAX_TOKEN_LIMIT\":\"${LLM_PROMPT_MAX_TOKEN_LIMIT}\",\"KNOWLEDGE_BASE_PREFIX_MESSAGE\":\"From Knowledge Base:\",\"KNOWLEDGE_BASE_SHOW_REFERENCES\":\"true\",\"KNOWLEDGE_BASE_S3_SIGNED_URLS\":\"true\",\"KNOWLEDGE_BASE_S3_SIGNED_URL_EXPIRE_SECS\":300,\"KNOWLEDGE_BASE_PROMPT_TEMPLATE\":\"${KNOWLEDGE_BASE_PROMPT_TEMPLATE}\",\"KNOWLEDGE_BASE_MAX_NUMBER_OF_RETRIEVED_RESULTS\":\"\",\"KNOWLEDGE_BASE_SEARCH_TYPE\":\"DEFAULT\",\"KNOWLEDGE_BASE_METADATA_FILTERS\":\"{}\",\"KNOWLEDGE_BASE_MODEL_PARAMS\":\"{}\",\"BEDROCK_GUARDRAIL_IDENTIFIER\":\"\",\"BEDROCK_GUARDRAIL_VERSION\":\"\"}",
            {
              "ES_USE_KEYWORD_FILTERS": {
                "Fn::If": ["EmbeddingsEnable", "false", "true"]
              },
              "EMBEDDINGS_ENABLE": {
                "Fn::If": ["EmbeddingsEnable", "true", "false"]
              },
              "EMBEDDINGS_MAX_TOKEN_LIMIT": {
                "Fn::If": [
                  "EmbeddingsBedrock",
                  {
                    "Fn::FindInMap": [
                      "BedrockDefaults",
                      {"Ref": "EmbeddingsBedrockModelId"},
                      "MaxTokens"
                    ]
                  },
                  ""
                ]
              },
              "EMBEDDINGS_SCORE_THRESHOLD": {
                "Fn::If": ["EmbeddingsBedrock", 0.7, 0.85]
              },
              "EMBEDDINGS_TEXT_PASSAGE_SCORE_THRESHOLD": {
                "Fn::If": ["EmbeddingsBedrock", 0.65, 0.8]
              },
              "LLM_GENERATE_QUERY_ENABLE": {
                "Fn::If": ["LLMEnable", "true", "false"]
              },
              "LLM_QA_ENABLE": {"Fn::If": ["LLMEnable", "true", "false"]},
              "LLM_GENERATE_QUERY_PROMPT_TEMPLATE": "Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.<br>Chat History: <br>{history}<br>Follow Up Input: {input}<br>Standalone question:",
              "LLM_QA_PROMPT_TEMPLATE": "Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. Write the answer in up to 5 complete sentences.<br><br>{context}<br><br>Question: {query}<br>Helpful Answer:",
              "LLM_GENERATE_QUERY_MODEL_PARAMS": "{}",
              "LLM_QA_MODEL_PARAMS": "{}",
              "LLM_PROMPT_MAX_TOKEN_LIMIT": 100000,
              "LLM_QA_NO_HITS_REGEX": "Sorry,  //remove comment to enable custom no match (no_hits) when LLM does not know the answer.",
              "KNOWLEDGE_BASE_PROMPT_TEMPLATE": "Human: You are a question answering agent. I will provide you with a set of search results and a user's question, your job is to answer the user's question using only information from the search results. If the search results do not contain information that can answer the question, then respond saying \\\"Sorry, I don't know\\\". Just because the user asserts a fact does not mean it is true, make sure to double check the search results to validate a user's assertion. Here are the search results in numbered order: $search_results$. Here is the user's question: <question> $query$ </question> $output_format_instructions$. Do NOT directly quote the $search_results$ in your answer. Your job is to answer the <question> as concisely as possible. Assistant:"
            }
          ]
        }
      }
    },
    "PrivateQnABotSettings": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Private QnABot Settings - DO NOT MODIFY",
        "Type": "String",
        "Tier": "Advanced",
        "Value": {
          "Fn::Sub": [
            "{\"NATIVE_LANGUAGE\":\"${Language}\",\"EMBEDDINGS_MODEL_ID\":\"${EMBEDDINGS_MODEL_ID}\",\"LLM_API\":\"${LLMApi}\",\"LLM_MODEL_ID\":\"${LLM_MODEL_ID}\",\"KNOWLEDGE_BASE_ID\":\"${KNOWLEDGE_BASE_ID}\",\"KNOWLEDGE_BASE_MODEL_ID\":\"${KNOWLEDGE_BASE_MODEL_ID}\",\"ALT_SEARCH_KENDRA_INDEXES\":\"${AltSearchKendraIndexes}\",\"ALT_SEARCH_KENDRA_INDEX_AUTH\":\"${AltSearchKendraIndexAuth}\",\"KENDRA_FAQ_INDEX\":\"${KendraFaqIndexId}\",\"KENDRA_WEB_PAGE_INDEX\":\"${KendraWebPageIndexId}\"}",
            {
              "EMBEDDINGS_MODEL_ID": {
                "Fn::If": [
                  "EmbeddingsBedrock",
                  {
                    "Fn::FindInMap": [
                      "BedrockDefaults",
                      {"Ref": "EmbeddingsBedrockModelId"},
                      "ModelID"
                    ]
                  },
                  ""
                ]
              },
              "LLM_MODEL_ID": {
                "Fn::If": ["LLMBedrock", {"Ref": "LLMBedrockModelId"}, ""]
              },
              "KNOWLEDGE_BASE_MODEL_ID": {
                "Fn::If": [
                  "BedrockKnowledgeBaseEnable",
                  {"Ref": "BedrockKnowledgeBaseModel"},
                  ""
                ]
              },
              "KNOWLEDGE_BASE_ID": {
                "Fn::If": [
                  "BedrockKnowledgeBaseEnable",
                  {"Ref": "BedrockKnowledgeBaseId"},
                  ""
                ]
              }
            }
          ]
        }
      }
    },
    "CustomQnABotSettings": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Custom QnABot Settings - Modify to override defaults, or to add new settings",
        "Type": "String",
        "Tier": "Advanced",
        "Value": "{}"
      }
    },
    "SolutionHelperParameter": {
      "Type": "AWS::SSM::Parameter",
      "Properties": {
        "Description": "Solution Helper Parameter - DO NOT MODIFY",
        "Type": "String",
        "Value": "{}"
      }
    },
    "SignupPermision": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["SignupLambda", "Arn"]},
        "Principal": "cognito-idp.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["UserPool", "Arn"]}
      }
    },
    "MessagePermision": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["MessageLambda", "Arn"]},
        "Principal": "cognito-idp.amazonaws.com",
        "SourceArn": {"Fn::GetAtt": ["UserPool", "Arn"]}
      }
    },
    "MessageLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-MessageLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "MessageLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nconst subject = 'QnABot Signup Verification Code';\n\nfunction message(code) {\n    return `Hello, Your QnABot verification code is: ${code}`;\n}\n\nfunction isEmailApproved(email, approvedDomain) {\n    if (!approvedDomain) return true;\n    \n    // Escape special regex characters in the domain\n    const escapedDomain = approvedDomain.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n    const regex = new RegExp(`^[A-Za-z0-9._%+-]+@${escapedDomain}$`);\n    return email.match(regex);\n}\n\nfunction setEmailResponse(event) {\n    event.response.emailSubject = subject;\n    event.response.emailMessage = message(event.request.codeParameter);\n}\n\nexports.handler = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        // Ensure response object exists\n        if (!event.response) {\n            event.response = {};\n        }\n        \n        const approvedDomain = process.env.APPROVED_DOMAIN;\n        const email = event.request.userAttributes.email;\n        \n        if (!isEmailApproved(email, approvedDomain)) {\n            // Throw error to reject user signup\n            throw new Error('EMAIL_DOMAIN_DENIED_ERR');\n        }\n        \n        setEmailResponse(event);\n        \n        // Return the event object for Cognito\n        return event;\n    } catch (error) {\n        console.log('Error in handler:', error);\n        // Re-throw to let Cognito handle the rejection\n        throw error;\n    }\n};\n"
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "MessageLambdaLogGroup"}},
        "MemorySize": "128",
        "Environment": {
          "Variables": {
            "APPROVED_DOMAIN": {
              "Fn::If": ["Domain", "EMPTY", {"Ref": "AWS::NoValue"}]
            }
          }
        },
        "Role": {"Fn::GetAtt": ["SignupLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Cognito"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "SignupLambdaLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-SignupLambda"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "SignupLambda": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "ZipFile": "/** ************************************************************************************************\n*   Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.                             *\n*   SPDX-License-Identifier: Apache-2.0                                                            *\n ************************************************************************************************ */\n\nfunction isEmailApproved(email, approvedDomain) {\n    if (!approvedDomain) return true;\n    \n    // Escape special regex characters in the domain\n    const escapedDomain = approvedDomain.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n    const regex = new RegExp(`^[A-Za-z0-9._%+-]+@${escapedDomain}$`);\n    return email.match(regex);\n}\n\nfunction handleAutoVerify(event) {\n    if (event.request.userAttributes.email_verified === 'True') {\n        event.response.autoVerifyEmail = true;\n        event.response.autoConfirmUser = true;\n    }\n}\n\nexports.handler = async (event, context) => {\n    console.log('Received event:', JSON.stringify(event, null, 2));\n\n    try {\n        // Ensure response object exists\n        if (!event.response) {\n            event.response = {};\n        }\n        \n        const approvedDomain = process.env.APPROVED_DOMAIN;\n        const email = event.request.userAttributes.email;\n        \n        if (!isEmailApproved(email, approvedDomain)) {\n            // Throw error to reject user signup\n            throw new Error('EMAIL_DOMAIN_DENIED_ERR');\n        }\n        \n        handleAutoVerify(event);\n        \n        console.log('Returning event:', JSON.stringify(event, null, 2));\n        \n        // Return the event object for Cognito\n        return event;\n    } catch (error) {\n        console.log('Error in handler:', error);\n        // Re-throw to let Cognito handle the rejection\n        throw error;\n    }\n};\n"
        },
        "Handler": "index.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "SignupLambdaLogGroup"}},
        "MemorySize": "128",
        "Environment": {
          "Variables": {
            "APPROVED_DOMAIN": {
              "Fn::If": ["Domain", "EMPTY", {"Ref": "AWS::NoValue"}]
            }
          }
        },
        "Role": {"Fn::GetAtt": ["SignupLambdaRole", "Arn"]},
        "Runtime": "nodejs24.x",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Layers": [{"Ref": "AwsSdkLayerLambdaLayer"}],
        "Tags": [{"Key": "Type", "Value": "Cognito"}]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "SignupLambdaRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": "lambda.amazonaws.com"},
              "Action": "sts:AssumeRole"
            }
          ]
        },
        "Path": "/",
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "SolutionHelperRole": {
      "Type": "AWS::IAM::Role",
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {"Service": ["lambda.amazonaws.com"]},
              "Action": ["sts:AssumeRole"]
            }
          ]
        },
        "Policies": [
          {
            "PolicyDocument": {
              "Statement": [
                {
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Effect": "Allow",
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                }
              ],
              "Version": "2012-10-17"
            },
            "PolicyName": "LambdaFunctionServiceRolePolicy"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "logs:CreateLogGroup",
                    "logs:CreateLogStream",
                    "logs:PutLogEvents"
                  ],
                  "Resource": {
                    "Fn::Join": [
                      "",
                      [
                        "arn:",
                        {"Ref": "AWS::Partition"},
                        ":logs:",
                        {"Ref": "AWS::Region"},
                        ":",
                        {"Ref": "AWS::AccountId"},
                        ":log-group:/aws/lambda/*"
                      ]
                    ]
                  }
                },
                {
                  "Effect": "Allow",
                  "Action": [
                    "ec2:CreateNetworkInterface",
                    "ec2:AssignPrivateIpAddresses",
                    "ec2:UnassignPrivateIpAddresses",
                    "ec2:DescribeNetworkInterfaces",
                    "ec2:DeleteNetworkInterface"
                  ],
                  "Resource": "*"
                }
              ]
            },
            "PolicyName": "lambdaVPCAccessExecutionRole"
          },
          {
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": [
                    "xray:PutTraceSegments",
                    "xray:PutTelemetryRecords",
                    "xray:GetSamplingRules",
                    "xray:GetSamplingTargets",
                    "xray:GetSamplingStatisticSummaries"
                  ],
                  "Resource": ["*"]
                }
              ]
            },
            "PolicyName": "xrayDaemonWriteAccess"
          },
          {
            "PolicyName": "SettingsTableReadAccess",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["dynamodb:Scan"],
                  "Resource": [
                    {
                      "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${SettingsTable}"
                    }
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "GetParameterPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:GetParameter"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:",
                          {"Fn::Sub": "${AWS::Partition}:"},
                          "ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "SolutionHelperParameter"}
                        ]
                      ]
                    }
                  ]
                }
              ]
            }
          },
          {
            "PolicyName": "PutParameterPolicy",
            "PolicyDocument": {
              "Version": "2012-10-17",
              "Statement": [
                {
                  "Effect": "Allow",
                  "Action": ["ssm:PutParameter"],
                  "Resource": [
                    {
                      "Fn::Join": [
                        "",
                        [
                          "arn:",
                          {"Fn::Sub": "${AWS::Partition}:"},
                          "ssm:",
                          {"Fn::Sub": "${AWS::Region}:"},
                          {"Fn::Sub": "${AWS::AccountId}:"},
                          "parameter/",
                          {"Ref": "SolutionHelperParameter"}
                        ]
                      ]
                    }
                  ]
                }
              ]
            }
          }
        ]
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W11",
              "reason": "This IAM role requires to have * resource on its permission policy"
            },
            {
              "id": "W12",
              "reason": "Lambda needs the following minimum required permissions to send trace data to X-Ray"
            }
          ]
        },
        "guard": {"SuppressedRules": ["IAM_NO_INLINE_POLICY_CHECK"]}
      }
    },
    "SolutionHelperCodeVersion": {
      "Type": "Custom::S3Version",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
        "Key": {"Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/solution-helper.zip"},
        "BuildDate": "2026-06-09T15:56:38.767Z"
      }
    },
    "SolutionHelperLogGroup": {
      "Type": "AWS::Logs::LogGroup",
      "Properties": {
        "LogGroupName": {
          "Fn::Join": [
            "-",
            [
              {"Fn::Sub": "/aws/lambda/${AWS::StackName}-SolutionHelper"},
              {
                "Fn::Select": [
                  "2",
                  {"Fn::Split": ["/", {"Ref": "AWS::StackId"}]}
                ]
              }
            ]
          ]
        },
        "RetentionInDays": {
          "Fn::If": [
            "LogRetentionPeriodIsNotZero",
            {"Ref": "LogRetentionPeriod"},
            {"Ref": "AWS::NoValue"}
          ]
        }
      },
      "Metadata": {
        "guard": {
          "SuppressedRules": [
            "CLOUDWATCH_LOG_GROUP_ENCRYPTED",
            "CW_LOGGROUP_RETENTION_PERIOD_CHECK"
          ]
        }
      }
    },
    "SolutionHelper": {
      "Type": "AWS::Lambda::Function",
      "Properties": {
        "Code": {
          "S3Bucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "S3Key": {
            "Fn::Sub": "qnabot-on-aws/v7.3.14/lambda/solution-helper.zip"
          },
          "S3ObjectVersion": {"Ref": "SolutionHelperCodeVersion"}
        },
        "Description": "This function generates UUID for each deployment and sends anonymized data to the AWS Solutions team",
        "Handler": "lambda_function.handler",
        "LoggingConfig": {"LogGroup": {"Ref": "SolutionHelperLogGroup"}},
        "Role": {"Fn::GetAtt": ["SolutionHelperRole", "Arn"]},
        "Environment": {
          "Variables": {
            "SOLUTION_PARAMETER": {"Ref": "SolutionHelperParameter"},
            "SETTINGS_TABLE": {"Ref": "SettingsTable"},
            "SOLUTION_ID": "SO0189"
          }
        },
        "Runtime": "python3.14",
        "Timeout": 300,
        "VpcConfig": {
          "Fn::If": [
            "VPCEnabled",
            {
              "SubnetIds": {"Ref": "VPCSubnetIdList"},
              "SecurityGroupIds": {"Ref": "VPCSecurityGroupIdList"}
            },
            {"Ref": "AWS::NoValue"}
          ]
        },
        "TracingConfig": {
          "Fn::If": ["XRAYEnabled", {"Mode": "Active"}, {"Ref": "AWS::NoValue"}]
        },
        "Tags": [{"Key": "Type", "Value": "Solution Helper"}]
      },
      "DependsOn": ["SolutionHelperRole"],
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W89",
              "reason": "This Lambda Function is not required to be inside VPC"
            },
            {
              "id": "W92",
              "reason": "This lambda function does not require to have ReservedConcurrentExecutions"
            }
          ]
        },
        "guard": {
          "SuppressedRules": ["LAMBDA_CONCURRENCY_CHECK", "LAMBDA_INSIDE_VPC"]
        }
      }
    },
    "SolutionHelperCreateUniqueID": {
      "Type": "Custom::CreateUUID",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["SolutionHelper", "Arn"]},
        "Resource": "UUID"
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete",
      "Condition": "SolutionHelperSendAnonymizedDataToAWS"
    },
    "SolutionHelperSendAnonymizedData": {
      "Type": "Custom::AnonymizedData",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["SolutionHelper", "Arn"]},
        "Resource": "AnonymizedMetric",
        "UUID": {"Fn::GetAtt": ["SolutionHelperCreateUniqueID", "UUID"]},
        "Region": {"Ref": "AWS::Region"},
        "SolutionId": "SO0189",
        "Version": "v7.3.14",
        "OpenSearchNodeInstanceType": {
          "Fn::If": [
            "CreateDomain",
            {"Ref": "OpenSearchNodeInstanceType"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "PublicOrPrivate": {"Ref": "PublicOrPrivate"},
        "Language": {"Ref": "Language"},
        "OpenSearchNodeCount": {
          "Fn::If": [
            "CreateDomain",
            {"Ref": "OpenSearchNodeCount"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "OpenSearchEBSVolumeSize": {
          "Fn::If": [
            "CreateDomain",
            {"Ref": "OpenSearchEBSVolumeSize"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "FulfillmentConcurrency": {"Ref": "FulfillmentConcurrency"},
        "InstallLexResponseBots": {"Ref": "InstallLexResponseBots"},
        "EmbeddingsApi": {"Ref": "EmbeddingsApi"},
        "EmbeddingsBedrockModelId": {
          "Fn::If": [
            "EmbeddingsBedrock",
            {"Ref": "EmbeddingsBedrockModelId"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "LLMApi": {"Ref": "LLMApi"},
        "LLMBedrockModelId": {
          "Fn::If": [
            "LLMBedrock",
            {"Ref": "LLMBedrockModelId"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "BedrockKnowledgeBaseModel": {
          "Fn::If": [
            "BedrockKnowledgeBaseEnable",
            {"Ref": "BedrockKnowledgeBaseModel"},
            {"Ref": "AWS::NoValue"}
          ]
        },
        "KendraPluginsEnabled": {
          "Fn::If": ["KendraPluginsEnabled", "YES", "NO"]
        },
        "OpenSearchFineGrainAccessControl": {
          "Ref": "OpenSearchFineGrainAccessControl"
        },
        "EnableStreaming": {"Ref": "EnableStreaming"}
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete",
      "Condition": "SolutionHelperSendAnonymizedDataToAWS"
    },
    "TestAllStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v7.3.14/templates/testall.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "S3Clean": {"Fn::GetAtt": ["S3Clean", "Arn"]},
          "LexV2BotId": {"Fn::GetAtt": ["LexV2Bot", "botId"]},
          "LexV2BotAliasId": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v7.3.14",
          "VarIndex": {"Fn::GetAtt": ["Var", "QnaIndex"]},
          "EsEndpoint": {"Fn::GetAtt": ["ESVar", "ESAddress"]},
          "EsProxyLambda": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
          "TestAllBucket": {"Ref": "TestAllBucket"},
          "ContentDesignerOutputBucket": {"Ref": "ContentDesignerOutputBucket"},
          "VPCSubnetIdList": {"Fn::Join": [",", {"Ref": "VPCSubnetIdList"}]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", {"Ref": "VPCSecurityGroupIdList"}]
          },
          "XraySetting": {"Ref": "XraySetting"},
          "AwsSdkLayerLambdaLayer": {"Ref": "AwsSdkLayerLambdaLayer"},
          "CommonModulesLambdaLayer": {"Ref": "CommonModulesLambdaLayer"},
          "LogRetentionPeriod": {"Ref": "LogRetentionPeriod"}
        }
      }
    },
    "Var": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "index": {"value": {"Ref": "AWS::StackName"}, "op": "toLowerCase"},
        "QnAType": "qna",
        "QuizType": "quiz",
        "QnaIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}"},
          "op": "toLowerCase"
        },
        "ResponseBotStackName": {
          "value": {"Fn::Sub": "${AWS::StackName}-examples"},
          "op": "toLowerCase"
        },
        "MetricsIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}-metrics"},
          "op": "toLowerCase"
        },
        "FeedbackIndex": {
          "value": {"Fn::Sub": "${AWS::StackName}-feedback"},
          "op": "toLowerCase"
        }
      }
    },
    "InfoVar": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Version": "7.3.14",
        "BuildDateString": "Tue Jun 09 2026 15:56:38 GMT+0000 (Coordinated Universal Time)",
        "BuildDate": "2026-06-09T15:56:38.767Z"
      }
    },
    "ESVar": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "ESArn": {
          "Fn::If": [
            "CreateDomain",
            {"Fn::GetAtt": ["OpensearchDomain", "DomainArn"]},
            {"Fn::GetAtt": ["ESInfo", "Arn"]}
          ]
        },
        "ESAddress": {
          "Fn::If": [
            "CreateDomain",
            {"Fn::GetAtt": ["OpensearchDomain", "DomainEndpoint"]},
            {"Fn::GetAtt": ["ESInfo", "Endpoint"]}
          ]
        },
        "ESDomain": {
          "Fn::If": ["CreateDomain", {"Ref": "OpensearchDomain"}, "EMPTY"]
        }
      }
    },
    "ApiUrl": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Name": {
          "Fn::Join": [
            "",
            [
              "https://",
              {"Ref": "API"},
              ".execute-api.",
              {"Ref": "AWS::Region"},
              ".amazonaws.com/prod"
            ]
          ]
        }
      }
    },
    "Urls": {
      "Type": "Custom::Variable",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "Designer": {
          "Fn::Join": [
            "",
            [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/static/index.html"]
          ]
        },
        "Client": {
          "Fn::Join": [
            "",
            [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/static/client.html"]
          ]
        },
        "OpenSearchDashboards": {
          "Fn::Sub": "${ESVar.ESAddress}/_dashboards/app/dashboards#/list"
        }
      }
    },
    "dashboard": {
      "Type": "AWS::CloudWatch::Dashboard",
      "Properties": {
        "DashboardName": {"Fn::Sub": "${AWS::Region}-${AWS::StackName}"},
        "DashboardBody": {
          "Fn::Sub": "{\"widgets\":[{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":0,\"properties\":{\"markdown\":\"# QnABot:${AWS::StackName} Dashboard\"}},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":3,\"properties\":{\"markdown\":\"## OpenSearch\"}},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ReadLatency\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"]],\"region\":\"${AWS::Region}\"},\"x\":0,\"y\":5},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ReadIOPS\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"],[\".\",\"ReadThroughput\",\".\",\".\",\".\",\".\",{\"yAxis\":\"right\"}]],\"region\":\"${AWS::Region}\"},\"x\":6,\"y\":5},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"CPUUtilization\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"]],\"region\":\"${AWS::Region}\"},\"x\":12,\"y\":5},{\"type\":\"metric\",\"x\":18,\"y\":5,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ClusterUsedSpace\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\"],[\".\",\"SearchableDocuments\",\".\",\".\",\".\",\".\",{\"yAxis\":\"right\"}]],\"region\":\"${AWS::Region}\"},\"height\":6,\"width\":6},{\"type\":\"metric\",\"width\":6,\"height\":6,\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/ES\",\"ClusterStatus.green\",\"DomainName\",\"${ESVar.ESDomain}\",\"ClientId\",\"${AWS::AccountId}\",{\"color\":\"#2ca02c\"}],[\".\",\"ClusterStatus.red\",\".\",\".\",\".\",\".\",{\"color\":\"#d62728\"}],[\".\",\"ClusterStatus.yellow\",\".\",\".\",\".\",\".\",{\"color\":\"#bcbd22\"}]],\"region\":\"${AWS::Region}\"},\"x\":0,\"y\":11},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":24,\"properties\":{\"markdown\":\"## Lambda Function\"}},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":26,\"properties\":{\"markdown\":\"### CustomResource\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${VersionLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"VersionLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":28},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${CFNLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"CFNLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":28},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESCFNProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESCFNProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":28},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":34,\"properties\":{\"markdown\":\"### Fulfillment\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${FulfillmentLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"FulfillmentLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":36},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":42,\"properties\":{\"markdown\":\"### Warmer\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESWarmerLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESWarmerLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":44},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":50,\"properties\":{\"markdown\":\"### Api\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambdaStart}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambdaStart\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexBuildLambdaPoll}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexBuildLambdaPoll\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${Lexv2BotLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"Lexv2BotLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":52},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${LexStatusLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"LexStatusLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${S3ListLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"S3ListLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ExampleS3ListLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ExampleS3ListLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":58},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ExampleS3ListPhotoLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ExampleS3ListPhotoLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":64},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${SchemaLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"SchemaLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":64},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":70,\"properties\":{\"markdown\":\"### Service\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${UtteranceLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"UtteranceLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESQidLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESQidLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESCleaningLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESCleaningLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":12,\"y\":72},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESProxyLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESProxyLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":18,\"y\":72},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":78,\"properties\":{\"markdown\":\"### Logging\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESLoggingLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESLoggingLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":80},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":86,\"properties\":{\"markdown\":\"### Query\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${ESQueryLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"ESQueryLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":88},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":94,\"properties\":{\"markdown\":\"### S3 Clean\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${S3Clean}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"S3Clean\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":96},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":102,\"properties\":{\"markdown\":\"### Cognito\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${MessageLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"MessageLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":104},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${SignupLambda}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"SignupLambda\",\"period\":300},\"height\":6,\"width\":6,\"x\":6,\"y\":104},{\"type\":\"text\",\"width\":24,\"height\":2,\"x\":0,\"y\":110,\"properties\":{\"markdown\":\"### Solution Helper\"}},{\"type\":\"metric\",\"properties\":{\"view\":\"timeSeries\",\"stacked\":false,\"metrics\":[[\"AWS/Lambda\",\"Errors\",\"FunctionName\",\"${SolutionHelper}\",{\"stat\":\"Sum\"}],[\".\",\"Invocations\",\".\",\".\",{\"stat\":\"Sum\"}],[\".\",\"Duration\",\".\",\".\",{\"yAxis\":\"right\"}],[\".\",\"Throttles\",\".\",\".\",{\"stat\":\"Sum\"}]],\"region\":\"${AWS::Region}\",\"title\":\"SolutionHelper\",\"period\":300},\"height\":6,\"width\":6,\"x\":0,\"y\":112}]}"
        }
      }
    },
    "API": {
      "Type": "AWS::ApiGateway::RestApi",
      "Properties": {
        "Name": {"Ref": "AWS::StackName"},
        "Description": "An Api interface for the admin actions on the QNA bot",
        "BinaryMediaTypes": ["image/png", "font/woff", "font/woff2"],
        "MinimumCompressionSize": 500000
      }
    },
    "Deployment": {
      "Type": "Custom::ApiDeployment",
      "Properties": {
        "ServiceToken": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
        "restApiId": {"Ref": "API"},
        "buildDate": "2026-06-09T15:56:38.770Z",
        "stage": "prod",
        "LexV2BotLocaleIds": {"Ref": "LexV2BotLocaleIds"}
      },
      "DependsOn": [
        "AlexaSchema",
        "BotPost",
        "BotGet",
        "HealthGet",
        "rootGet",
        "QuestionsGet",
        "QuestionsDelete",
        "QuestionHead",
        "QuestionPut",
        "QuestionsOptions",
        "QuestionDelete",
        "ProxyAnyGet",
        "ProxyAnyHead",
        "FontsProxyGet",
        "DesignerLoginResourceGet",
        "ClientLoginResourceGet",
        "JobsGet",
        "testallsList",
        "testallPut",
        "testallGet",
        "testallDelete",
        "exportsList",
        "exportPut",
        "exportGet",
        "exportDelete",
        "importsList",
        "importGet",
        "importDelete",
        "ExamplesGet",
        "photosList",
        "photoGet",
        "DocumentsList",
        "ExampleGet",
        "ExampleHead",
        "ServicesGet",
        "ImagesProxyGet",
        "InvokePermissionLexBuildLambdaStart",
        "InvokePermissionLexv2BotLambda",
        "InvokePermissionUtteranceLambda",
        "InvokePermissionESQidLambda",
        "InvokePermissionESCleaningLambda",
        "InvokePermissionESProxyLambda",
        "InvokePermissionLexProxyLambda",
        "InvokePermissionS3ListLambda",
        "InvokePermissionExampleS3ListLambda",
        "InvokePermissionExampleS3ListPhotoLambda",
        "InvokePermissionSchemaLambda"
      ]
    },
    "Stage": {
      "Type": "AWS::ApiGateway::Stage",
      "Properties": {
        "DeploymentId": {"Ref": "Deployment"},
        "RestApiId": {"Ref": "API"},
        "StageName": "prod",
        "MethodSettings": [
          {
            "CacheDataEncrypted": true,
            "CachingEnabled": true,
            "DataTraceEnabled": false,
            "HttpMethod": "*",
            "LoggingLevel": "INFO",
            "ResourcePath": "/*"
          }
        ],
        "Variables": {
          "Id": "QnABot",
          "Region": {"Ref": "AWS::Region"},
          "CognitoEndpoint": {"Fn::GetAtt": ["DesignerLogin", "Domain"]},
          "DesignerLoginUrl": {
            "Fn::Join": [
              "",
              [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/designer"]
            ]
          },
          "ClientLoginUrl": {
            "Fn::If": [
              "Public",
              {"Fn::GetAtt": ["Urls", "Client"]},
              {
                "Fn::Join": [
                  "",
                  [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/client"]
                ]
              }
            ]
          },
          "StreamingWebSocketEndpoint": {
            "Fn::If": [
              "StreamingEnabled",
              {
                "Fn::GetAtt": [
                  "StreamingStack",
                  "Outputs.StreamingWebSocketEndpoint"
                ]
              },
              ""
            ]
          }
        }
      },
      "Metadata": {
        "cfn_nag": {
          "rules_to_suppress": [
            {
              "id": "W64",
              "reason": "This apiGateway stage does not require to be associated with a usage plan"
            },
            {
              "id": "W69",
              "reason": "This apiGateway stage does not require to have access logging"
            }
          ]
        }
      }
    },
    "ApiGatewayAccount": {
      "Type": "AWS::ApiGateway::Account",
      "Properties": {
        "CloudWatchRoleArn": {
          "Fn::GetAtt": ["ApiGatewayCloudWatchLogsRole", "Arn"]
        }
      }
    },
    "DocumentationVersion": {
      "Type": "AWS::ApiGateway::DocumentationVersion",
      "DependsOn": ["BotDoc"],
      "Properties": {
        "Description": "",
        "DocumentationVersion": "1.0",
        "RestApiId": {"Ref": "API"}
      }
    },
    "InvokePermissionLexBuildLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionLexBuildLambdaStart": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambdaStart", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionLexBuildLambdaPoll": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexBuildLambdaPoll", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionLexv2BotLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["Lexv2BotLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionUtteranceLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["UtteranceLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionESQidLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESQidLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionESCleaningLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESCleaningLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionESProxyLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionLexProxyLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexProxyLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionLexStatusLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["LexStatusLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionS3ListLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["S3ListLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionExampleS3ListLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ExampleS3ListLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionExampleS3ListPhotoLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["ExampleS3ListPhotoLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "InvokePermissionSchemaLambda": {
      "Type": "AWS::Lambda::Permission",
      "Properties": {
        "Action": "lambda:InvokeFunction",
        "FunctionName": {"Fn::GetAtt": ["SchemaLambda", "Arn"]},
        "Principal": "apigateway.amazonaws.com",
        "SourceAccount": {"Ref": "AWS::AccountId"}
      }
    },
    "StreamingStack": {
      "Type": "AWS::CloudFormation::Stack",
      "Condition": "StreamingEnabled",
      "Properties": {
        "TemplateURL": {
          "Fn::Sub": "https://solutions-${AWS::Region}.s3.${AWS::Region}.amazonaws.com/qnabot-on-aws/v7.3.14/templates/streaming.json"
        },
        "Parameters": {
          "CFNLambda": {"Fn::GetAtt": ["CFNLambda", "Arn"]},
          "CFNInvokePolicy": {"Ref": "CFNInvokePolicy"},
          "S3Clean": {"Fn::GetAtt": ["S3Clean", "Arn"]},
          "BootstrapBucket": {"Fn::Sub": "solutions-${AWS::Region}"},
          "BootstrapPrefix": "qnabot-on-aws/v7.3.14",
          "LogRetentionPeriod": {"Ref": "LogRetentionPeriod"},
          "XraySetting": {"Ref": "XraySetting"},
          "VPCSubnetIdList": {"Fn::Join": [",", {"Ref": "VPCSubnetIdList"}]},
          "VPCSecurityGroupIdList": {
            "Fn::Join": [",", {"Ref": "VPCSecurityGroupIdList"}]
          }
        }
      }
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "(SO0189) QnABot with admin and client websites - Version v7.3.14",
  "Mappings": {
    "SolutionHelperAnonymizedData": {"SendAnonymizedData": {"Data": "Yes"}},
    "BedrockDefaults": {
      "amazon.titan-embed-text-v1": {
        "ModelID": "amazon.titan-embed-text-v1",
        "MaxTokens": 8000,
        "EmbeddingsDimensions": 1536
      },
      "amazon.titan-embed-text-v2": {
        "ModelID": "amazon.titan-embed-text-v2:0",
        "MaxTokens": 8000,
        "EmbeddingsDimensions": 1024
      },
      "amazon.nova-2-multimodal-embeddings-v1": {
        "ModelID": "amazon.nova-2-multimodal-embeddings-v1:0",
        "MaxTokens": 8172,
        "EmbeddingsDimensions": 3072
      },
      "cohere.embed-english-v3": {
        "ModelID": "cohere.embed-english-v3",
        "MaxTokens": 512,
        "EmbeddingsDimensions": 1024
      },
      "cohere.embed-multilingual-v3": {
        "ModelID": "cohere.embed-multilingual-v3",
        "MaxTokens": 512,
        "EmbeddingsDimensions": 1024
      },
      "global.cohere.embed-v4": {
        "ModelID": "global.cohere.embed-v4:0",
        "MaxTokens": 128000,
        "EmbeddingsDimensions": 1536
      }
    }
  },
  "Outputs": {
    "ContentDesignerURL": {
      "Value": {
        "Fn::Join": [
          "",
          [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/designer"]
        ]
      }
    },
    "ClientURL": {
      "Value": {
        "Fn::If": [
          "Public",
          {"Fn::GetAtt": ["Urls", "Client"]},
          {
            "Fn::Join": [
              "",
              [{"Fn::GetAtt": ["ApiUrl", "Name"]}, "/pages/client"]
            ]
          }
        ]
      }
    },
    "CloudWatchDashboardURL": {
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://console.aws.amazon.com/cloudwatch/home?",
            "region=",
            {"Ref": "AWS::Region"},
            "#dashboards:name=",
            {"Ref": "dashboard"}
          ]
        ]
      }
    },
    "UserPoolURL": {
      "Value": {
        "Fn::Join": [
          "",
          [
            "https://console.aws.amazon.com/cognito/users/",
            "?region=",
            {"Ref": "AWS::Region"},
            "#/pool/",
            {"Ref": "UserPool"},
            "/details"
          ]
        ]
      }
    },
    "LexV2BotName": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botName"]}},
    "LexV2BotId": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botId"]}},
    "LexV2BotAlias": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botAlias"]}},
    "LexV2BotAliasId": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botAliasId"]}},
    "LexV2Intent": {"Value": {"Fn::GetAtt": ["LexV2Bot", "botIntent"]}},
    "LexV2IntentFallback": {
      "Value": {"Fn::GetAtt": ["LexV2Bot", "botIntentFallback"]}
    },
    "LexV2BotLocaleIds": {
      "Value": {"Fn::GetAtt": ["LexV2Bot", "botLocaleIds"]}
    },
    "FeedbackSNSTopic": {
      "Condition": "BuildExamples",
      "Value": {"Fn::GetAtt": ["ExamplesStack", "Outputs.FeedbackSNSTopic"]}
    },
    "ESProxyLambda": {"Value": {"Fn::GetAtt": ["ESProxyLambda", "Arn"]}},
    "OpenSearchDomainEndpoint": {
      "Value": {
        "Fn::Join": ["", ["https://", {"Fn::GetAtt": ["ESVar", "ESAddress"]}]]
      }
    },
    "OpenSearchIndex": {"Value": {"Fn::GetAtt": ["Var", "index"]}},
    "MetricsBucket": {"Value": {"Ref": "MetricsBucket"}},
    "TestAllBucket": {"Value": {"Ref": "TestAllBucket"}},
    "ContentDesignerOutputBucket": {
      "Value": {"Ref": "ContentDesignerOutputBucket"}
    },
    "StreamingWebSocketEndpoint": {
      "Condition": "StreamingEnabled",
      "Value": {
        "Fn::GetAtt": ["StreamingStack", "Outputs.StreamingWebSocketEndpoint"]
      }
    },
    "SettingsTable": {"Value": {"Ref": "SettingsTable"}}
  },
  "Parameters": {
    "Email": {
      "Type": "String",
      "Description": "Email address for the admin user. This email address will receive a temporary password to access the QnABot on AWS content designer.",
      "AllowedPattern": ".+\\@.+\\..+",
      "ConstraintDescription": "Must be valid email address eg. johndoe@example.com"
    },
    "Username": {
      "Type": "String",
      "Description": "This username will be used to sign in to QnABot on AWS content designer console.",
      "Default": "Admin",
      "AllowedPattern": "[^ ]+",
      "ConstraintDescription": "Must not be empty or contain spaces"
    },
    "KendraWebPageIndexId": {
      "Type": "String",
      "Description": "Optional: Id of the Amazon Kendra index to use for the web crawler, a custom data source will automatically be added to the specified index. Also use this index id in AltSearchKendraIndexes to enable fallback.",
      "Default": "",
      "AllowedPattern": "[^ ]*",
      "ConstraintDescription": "Must be a valid Amazon Kendra index id or left blank"
    },
    "KendraFaqIndexId": {
      "Type": "String",
      "Description": "Optional: Id of the Amazon Kendra Index to use for syncing OpenSearch questions and answers",
      "Default": "",
      "AllowedPattern": "[^ ]*",
      "ConstraintDescription": "Must be a valid Amazon Kendra index id or left blank"
    },
    "AltSearchKendraIndexes": {
      "Type": "String",
      "Description": "Optional: A comma separated String value specifying ids of one or more Amazon Kendra indexes to be used for Kendra fallback",
      "Default": "",
      "AllowedPattern": "[^ ]*",
      "ConstraintDescription": "Must be a list of valid Amazon Kendra index id(s) or left blank"
    },
    "AltSearchKendraIndexAuth": {
      "Type": "String",
      "Description": "Set to true if using Kendra Index(es) with access control enabled. This tells QnABot to pass an authentication token to Kendra Index(es) used for Kendra fallback if it is available.",
      "AllowedValues": ["true", "false"],
      "Default": "false"
    },
    "PublicOrPrivate": {
      "Type": "String",
      "Description": "Choose whether access to the QnABot client should be publicly available or restricted to users in QnABot UserPool.",
      "AllowedValues": ["PUBLIC", "PRIVATE"],
      "Default": "PRIVATE"
    },
    "Language": {
      "Type": "String",
      "Description": "Choose the primary Language for your QnABot deployment. Note: Picking non-English may correspond with limited functionalities",
      "AllowedValues": [
        "Arabic",
        "Armenian",
        "Basque",
        "Bengali",
        "Brazilian",
        "Bulgarian",
        "Catalan",
        "Chinese",
        "Czech",
        "Danish",
        "Dutch",
        "English",
        "Estonian",
        "Finnish",
        "French",
        "Galician",
        "German",
        "Greek",
        "Hindi",
        "Hungarian",
        "Indonesian",
        "Irish",
        "Italian",
        "Latvian",
        "Lithuanian",
        "Norwegian",
        "Portuguese",
        "Romanian",
        "Russian",
        "Sorani",
        "Spanish",
        "Swedish",
        "Turkish",
        "Thai"
      ],
      "Default": "English"
    },
    "LexV2BotLocaleIds": {
      "Description": "Languages for QnABot on AWS voice interaction using LexV2. Specify as a comma separated list of valid Locale IDs without empty spaces - see https://github.com/aws-solutions/qnabot-on-aws/blob/main/source/docs/multilanguage_support/README.md#supported-languages",
      "Type": "String",
      "Default": "en_US,es_US,fr_CA",
      "AllowedPattern": "[^ ]+",
      "ConstraintDescription": "Must be a valid comma separated list of Locale IDs"
    },
    "InstallLexResponseBots": {
      "Description": "You can configure your chatbot to ask questions and process your end user's answers for surveys, quizzes,... (Elicit Response Feature). If the Elicit Response feature is not needed, choose 'false' to skip the sample Lex Response Bot installation - see https://docs.aws.amazon.com/solutions/latest/qnabot-on-aws/configuring-the-chatbot-to-ask-the-questions-and-use-response-bots.html",
      "Type": "String",
      "AllowedValues": ["true", "false"],
      "Default": "true"
    },
    "FulfillmentConcurrency": {
      "Type": "Number",
      "Description": "The amount of provisioned concurrency for the fulfillment Lambda function - see: https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html",
      "Default": 0,
      "MinValue": 0
    },
    "OpenSearchDedicatedMasterNodes": {
      "Type": "String",
      "Description": "Enable OpenSearch add dedicated master nodes to increase cluster stability. Please note that deploying additional nodes will increase cost, see - https://aws.amazon.com/opensearch-service/pricing/",
      "Default": "DISABLED",
      "AllowedValues": ["DISABLED", "ENABLED"]
    },
    "OpenSearchMasterNodeInstanceType": {
      "Type": "String",
      "Description": "Required when OpenSearchDedicatedMasterNodes is ENABLED. OpenSearch instance type for master nodes in the domain. Default recommendation for production deployments is m6g.large.search (see https://docs.aws.amazon.com/opensearch-service/latest/developerguide/supported-instance-types.html for other options).",
      "Default": "m6g.large.search",
      "AllowedPattern": "^\\w+\\.\\w+\\.search$",
      "ConstraintDescription": "Must be a valid OpenSearch instance type"
    },
    "OpenSearchMasterNodeCount": {
      "Type": "String",
      "Description": "Required when OpenSearchDedicatedMasterNodes is ENABLED. Number of dedicated master nodes to add in your Amazon OpenSearch Service domain. '3' is the minimum default value. See - https://docs.aws.amazon.com/opensearch-service/latest/developerguide/managedomains-dedicatedmasternodes.html#dedicatedmasternodes-number",
      "AllowedValues": ["3", "5"],
      "Default": "3"
    },
    "OpenSearchNodeInstanceType": {
      "Type": "String",
      "Description": "OpenSearch instance type for data nodes in the domain. Default recommendation for production deployments is m6g.large.search (see https://docs.aws.amazon.com/opensearch-service/latest/developerguide/supported-instance-types.html for other options).",
      "Default": "m6g.large.search",
      "AllowedPattern": "^\\w+\\.\\w+\\.search$",
      "ConstraintDescription": "Must be a valid OpenSearch instance type"
    },
    "OpenSearchNodeCount": {
      "Type": "String",
      "Description": "Number of data nodes in Amazon OpenSearch Service domain - '4' is recommended for fault tolerant production deployments.",
      "AllowedValues": ["1", "2", "4"],
      "Default": "4"
    },
    "OpenSearchEBSVolumeSize": {
      "Type": "Number",
      "Description": "Size in GB of each EBS volume attached to OpenSearch node instances - '10' is the minimum default volume size.",
      "Default": 10,
      "MinValue": 10
    },
    "OpenSearchDashboardsRetentionMinutes": {
      "Type": "Number",
      "Description": "To conserve storage in Amazon OpenSearch, metrics and feedback data used to populate the OpenSearch dashboards are automatically deleted after this period (default 43200 minutes = 30 days). Monitor 'Free storage space' for your OpenSearch domain to ensure that you have sufficient space available to store data for the desired retention period.",
      "Default": 43200,
      "MinValue": 0
    },
    "OpenSearchFineGrainAccessControl": {
      "Type": "String",
      "AllowedValues": ["FALSE", "TRUE"],
      "Description": "Set to FALSE if Fine-grained access control does not need to be enabled by default. Once fine-grained access control is enabled, it cannot be disabled. Please note that it may take an additional 30-60 minutes for AWS OpenSearch Service to apply these settings to the OpenSearch domain after the stack has been deployed. (see https://docs.aws.amazon.com/opensearch-service/latest/developerguide/fgac.html for additional details).",
      "ConstraintDescription": "Allowed Values are FALSE or TRUE",
      "Default": "TRUE"
    },
    "VPCSubnetIdList": {
      "Type": "List<AWS::EC2::Subnet::Id>",
      "Description": "Set to a list of Subnet IDs belonging to the target VPC you want to deploy QnABot on AWS in.",
      "AllowedPattern": ".+",
      "ConstraintDescription": "Must be a list of valid subnet IDs"
    },
    "VPCSecurityGroupIdList": {
      "Type": "List<AWS::EC2::SecurityGroup::Id>",
      "Description": "Set to a list of Security Group IDs used by QnABot when deployed within a VPC.",
      "AllowedPattern": ".+",
      "ConstraintDescription": "Must be a list of valid security group IDs"
    },
    "XraySetting": {
      "Type": "String",
      "Description": "Configure Lambdas with X-Ray enabled",
      "AllowedValues": ["FALSE", "TRUE"],
      "Default": "FALSE",
      "ConstraintDescription": "Allowed Values are FALSE or TRUE"
    },
    "EmbeddingsApi": {
      "Type": "String",
      "Description": "Enable QnABot semantics search using Embeddings from a pre-trained Large Language Model. To use a custom LAMBDA function, provide additional parameters below.",
      "AllowedValues": ["DISABLED", "BEDROCK", "LAMBDA"],
      "Default": "DISABLED"
    },
    "EmbeddingsBedrockModelId": {
      "Type": "String",
      "Description": "Required when EmbeddingsApi is BEDROCK.",
      "AllowedValues": [
        "amazon.titan-embed-text-v1",
        "amazon.titan-embed-text-v2",
        "amazon.nova-2-multimodal-embeddings-v1",
        "cohere.embed-english-v3",
        "cohere.embed-multilingual-v3",
        "global.cohere.embed-v4"
      ],
      "Default": "amazon.nova-2-multimodal-embeddings-v1"
    },
    "EmbeddingsLambdaArn": {
      "Type": "String",
      "AllowedPattern": "^(|arn:aws:lambda:.*)$",
      "Description": "Required when EmbeddingsApi is LAMBDA. Provide the ARN for a Lambda function that takes JSON {\"inputtext\":\"string\"}, and returns JSON {\"embedding\":[...]}",
      "Default": "",
      "ConstraintDescription": "Must be a valid Lambda ARN or leave blank"
    },
    "EmbeddingsLambdaDimensions": {
      "Type": "Number",
      "MinValue": 1,
      "Description": "Required when EmbeddingsApi is LAMBDA. Provide number of dimensions for embeddings returned by the EmbeddingsLambda function specified above.",
      "Default": 1536
    },
    "LLMApi": {
      "Type": "String",
      "Description": "Optionally enable QnABot on AWS question disambiguation and generative question answering using an LLM. Selecting the LAMBDA option allows for configuration with other LLMs.",
      "AllowedValues": ["DISABLED", "LAMBDA", "BEDROCK"],
      "Default": "DISABLED"
    },
    "LLMBedrockModelId": {
      "Type": "String",
      "Description": "Required when LLMApi is BEDROCK. Provide a valid foundation model ID or inference profile ID. See (https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) and (https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html).",
      "AllowedPattern": "^([\\w\\.-]+:[0-9]+|[\\w\\.-]+)$",
      "ConstraintDescription": "Must be a valid Bedrock foundation model ID or inference profile ID.",
      "Default": "global.anthropic.claude-haiku-4-5-20251001-v1:0"
    },
    "LLMLambdaArn": {
      "Type": "String",
      "AllowedPattern": "^(|arn:aws:lambda:.*)$",
      "Description": "Required if LLMApi is LAMBDA. Provide ARN for a Lambda function that takes JSON {\"prompt\":\"string\", \"settings\":{key:value,..}}, and returns JSON {\"generated_text\":\"string\"}",
      "Default": "",
      "ConstraintDescription": "Must be a valid Lambda ARN or leave blank"
    },
    "BedrockKnowledgeBaseId": {
      "Type": "String",
      "Description": "Optional: ID of an existing Bedrock knowledge base. This setting enables the use of Bedrock knowledge bases as a fallback mechanism when a match is not found in OpenSearch.",
      "AllowedPattern": "[0-9A-Z]{10}|^$",
      "Default": "",
      "ConstraintDescription": "Must be a valid Bedrock knowledge base id or leave blank"
    },
    "BedrockKnowledgeBaseModel": {
      "Type": "String",
      "Description": "Required if BedrockKnowledgeBaseId is not empty. Provide a valid foundation model ID or inference profile id to use with the Bedrock knowledge base. See (https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html) and (https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html).",
      "AllowedPattern": "^([\\w\\.-]+:[0-9]+|[\\w\\.-]+)$",
      "ConstraintDescription": "Must be a valid Bedrock foundation model ID or inference profile ID.",
      "Default": "global.anthropic.claude-haiku-4-5-20251001-v1:0"
    },
    "LogRetentionPeriod": {
      "Type": "Number",
      "Description": "Optional: The number of days to keep logs before expiring. If you would like your logs to never expire, leave this value as 0.",
      "Default": 0,
      "AllowedValues": [
        0,
        1,
        3,
        5,
        7,
        14,
        30,
        60,
        90,
        120,
        150,
        180,
        365,
        400,
        545,
        731,
        1096,
        1827,
        2192,
        2557,
        2922,
        3288,
        3653
      ],
      "MinValue": 0
    },
    "EnableStreaming": {
      "Type": "String",
      "Description": "Set to TRUE to deploy the streaming resources using for LLMs.",
      "Default": "FALSE",
      "AllowedValues": ["TRUE", "FALSE"]
    }
  },
  "Conditions": {
    "Public": {"Fn::Equals": [{"Ref": "PublicOrPrivate"}, "PUBLIC"]},
    "AdminSignUp": {"Fn::Equals": [true, true]},
    "XRAYEnabled": {"Fn::Equals": [{"Ref": "XraySetting"}, "TRUE"]},
    "StreamingEnabled": {"Fn::Equals": [{"Ref": "EnableStreaming"}, "TRUE"]},
    "FGACEnabled": {"Fn::Equals": [true, true]},
    "Domain": {"Fn::Equals": [true, false]},
    "BuildExamples": {"Fn::Equals": [true, true]},
    "CreateDomain": {"Fn::Equals": [true, true]},
    "DontCreateDomain": {"Fn::Equals": [true, false]},
    "VPCEnabled": {
      "Fn::Not": [
        {
          "Fn::Equals": [
            "",
            {"Fn::Join": ["", {"Ref": "VPCSecurityGroupIdList"}]}
          ]
        }
      ]
    },
    "CreateConcurrency": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "FulfillmentConcurrency"}, "0"]}]
    },
    "SingleNode": {"Fn::Equals": [{"Ref": "OpenSearchNodeCount"}, "1"]},
    "MasterNodesEnabled": {
      "Fn::Equals": [{"Ref": "OpenSearchDedicatedMasterNodes"}, "ENABLED"]
    },
    "BedrockKnowledgeBaseEnable": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "BedrockKnowledgeBaseId"}, ""]}]
    },
    "BedrockEnable": {
      "Fn::Or": [
        {"Fn::Equals": [{"Ref": "LLMApi"}, "BEDROCK"]},
        {"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "BEDROCK"]}
      ]
    },
    "EmbeddingsEnable": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "DISABLED"]}]
    },
    "EmbeddingsBedrock": {"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "BEDROCK"]},
    "EmbeddingsLambda": {"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "LAMBDA"]},
    "EmbeddingsLambdaArn": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "EmbeddingsLambdaArn"}, ""]}]
    },
    "LLMEnable": {"Fn::Not": [{"Fn::Equals": [{"Ref": "LLMApi"}, "DISABLED"]}]},
    "LLMBedrock": {"Fn::Equals": [{"Ref": "LLMApi"}, "BEDROCK"]},
    "LLMLambda": {"Fn::Equals": [{"Ref": "LLMApi"}, "LAMBDA"]},
    "LLMLambdaArn": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "LLMLambdaArn"}, ""]}]
    },
    "SolutionHelperSendAnonymizedDataToAWS": {
      "Fn::Equals": [
        {
          "Fn::FindInMap": [
            "SolutionHelperAnonymizedData",
            "SendAnonymizedData",
            "Data"
          ]
        },
        "Yes"
      ]
    },
    "KendraPluginsEnabled": {
      "Fn::Or": [
        {"Fn::Not": [{"Fn::Equals": [{"Ref": "KendraWebPageIndexId"}, ""]}]},
        {"Fn::Not": [{"Fn::Equals": [{"Ref": "KendraFaqIndexId"}, ""]}]},
        {"Fn::Not": [{"Fn::Equals": [{"Ref": "AltSearchKendraIndexes"}, ""]}]}
      ]
    },
    "LogRetentionPeriodIsNotZero": {
      "Fn::Not": [{"Fn::Equals": [{"Ref": "LogRetentionPeriod"}, 0]}]
    }
  },
  "Rules": {
    "RequireLambdaArnForLambdaEmbeddingsApi": {
      "RuleCondition": {"Fn::Equals": [{"Ref": "EmbeddingsApi"}, "LAMBDA"]},
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [{"Fn::Equals": [{"Ref": "EmbeddingsLambdaArn"}, ""]}]
          },
          "AssertDescription": "EmbeddingsLambdaArn is required when EmbeddingsApi is set to LAMBDA."
        }
      ]
    }
  },
  "Metadata": {
    "AWS::CloudFormation::Interface": {
      "ParameterGroups": [
        {
          "Label": {
            "default": "Step 2A: Set Basic Chatbot Parameters (required)"
          },
          "Parameters": [
            "Email",
            "Username",
            "PublicOrPrivate",
            "Language",
            "OpenSearchDedicatedMasterNodes",
            "OpenSearchMasterNodeInstanceType",
            "OpenSearchMasterNodeCount",
            "OpenSearchNodeInstanceType",
            "OpenSearchNodeCount",
            "OpenSearchEBSVolumeSize",
            "OpenSearchDashboardsRetentionMinutes",
            "OpenSearchFineGrainAccessControl",
            "LexV2BotLocaleIds",
            "LexBotVersion",
            "InstallLexResponseBots",
            "FulfillmentConcurrency",
            "XraySetting"
          ]
        },
        {
          "Label": {
            "default": "Step 2B: Set VPC parameters to deploy QnABot in an existing VPC (required)"
          },
          "Parameters": ["VPCSubnetIdList", "VPCSecurityGroupIdList"]
        },
        {
          "Label": {
            "default": "Step 2C: Enable LLM for Semantic Search with Embeddings (optional)"
          },
          "Parameters": [
            "EmbeddingsApi",
            "EmbeddingsBedrockModelId",
            "EmbeddingsLambdaArn",
            "EmbeddingsLambdaDimensions"
          ]
        },
        {
          "Label": {
            "default": "Step 2D: Enable LLM Retrieval and generative text question answering to use with Fallback Option (optional)"
          },
          "Parameters": [
            "LLMApi",
            "LLMBedrockModelId",
            "LLMLambdaArn",
            "EnableStreaming"
          ]
        },
        {
          "Label": {
            "default": "Step 2E: Select Data Sources as Fallback Option (optional)"
          },
          "Parameters": [
            "KendraWebPageIndexId",
            "KendraFaqIndexId",
            "AltSearchKendraIndexes",
            "BedrockKnowledgeBaseId",
            "BedrockKnowledgeBaseModel"
          ]
        }
      ]
    }
  }
}