From e6c6e6931bda46132e082a974fb92b42016d8528 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Tue, 30 May 2023 20:28:46 -0400 Subject: [PATCH 01/12] vpc lattice event type --- .../utilities/data_classes/vpc_lattice.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 aws_lambda_powertools/utilities/data_classes/vpc_lattice.py diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py new file mode 100644 index 00000000000..803f3c02a70 --- /dev/null +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -0,0 +1,36 @@ +from typing import Dict + +from aws_lambda_powertools.utilities.data_classes.common import ( + DictWrapper, +) + +class VpcLatticeEvent(DictWrapper): + @property + def body(self) -> str: + """The VPC Lattice body.""" + return self["body"] + + @property + def headers(self) -> Dict[str, str]: + """The VPC Lattice event headers.""" + return self["headers"] + + @property + def is_base64_encoded(self) -> bool: + """A boolean flag to indicate if the applicable request payload is Base64-encode""" + return self["is_base64_encoded"] + + @property + def method(self) -> str: + """The VPC Lattice method used. Valid values include: DELETE, GET, HEAD, OPTIONS, PATCH, POST, and PUT.""" + return self["method"] + + @property + def query_string_parameters(self) -> Dict[str, str]: + """The request query string parameters.""" + return self["query_string_parameters"] + + @property + def raw_path(self) -> str: + """The raw VPC Lattice request path.""" + return self["raw_path"] From 306efc6ae8efa93b53b9cea72c00e0a44bd237e1 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Tue, 30 May 2023 20:33:56 -0400 Subject: [PATCH 02/12] adding to init --- aws_lambda_powertools/utilities/data_classes/__init__.py | 2 ++ aws_lambda_powertools/utilities/data_classes/vpc_lattice.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/data_classes/__init__.py b/aws_lambda_powertools/utilities/data_classes/__init__.py index 1d268fef7cb..420b953fda1 100644 --- a/aws_lambda_powertools/utilities/data_classes/__init__.py +++ b/aws_lambda_powertools/utilities/data_classes/__init__.py @@ -20,6 +20,7 @@ from .ses_event import SESEvent from .sns_event import SNSEvent from .sqs_event import SQSEvent +from .vpc_lattice import VPCLattice __all__ = [ "APIGatewayProxyEvent", @@ -42,4 +43,5 @@ "SNSEvent", "SQSEvent", "event_source", + "VPCLatticeEvent", ] diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py index 803f3c02a70..da9a7ebb50a 100644 --- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -4,7 +4,7 @@ DictWrapper, ) -class VpcLatticeEvent(DictWrapper): +class VPCLatticeEvent(DictWrapper): @property def body(self) -> str: """The VPC Lattice body.""" From c742470de4380aff3b8123884a5ed54ca30e85a7 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Tue, 30 May 2023 20:34:33 -0400 Subject: [PATCH 03/12] fixing import name --- aws_lambda_powertools/utilities/data_classes/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/data_classes/__init__.py b/aws_lambda_powertools/utilities/data_classes/__init__.py index 420b953fda1..076616b95d2 100644 --- a/aws_lambda_powertools/utilities/data_classes/__init__.py +++ b/aws_lambda_powertools/utilities/data_classes/__init__.py @@ -20,7 +20,7 @@ from .ses_event import SESEvent from .sns_event import SNSEvent from .sqs_event import SQSEvent -from .vpc_lattice import VPCLattice +from .vpc_lattice import VPCLatticeEvent __all__ = [ "APIGatewayProxyEvent", From 7d3b1f9451409fa2b3c0e235c0cd570809d1fa8c Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Thu, 1 Jun 2023 07:04:27 -0400 Subject: [PATCH 04/12] adding load test event --- tests/events/vpcLatticeEvent.json | 13 +++++++++++++ tests/functional/test_data_classes.py | 12 ++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/events/vpcLatticeEvent.json diff --git a/tests/events/vpcLatticeEvent.json b/tests/events/vpcLatticeEvent.json new file mode 100644 index 00000000000..4d9de9563f6 --- /dev/null +++ b/tests/events/vpcLatticeEvent.json @@ -0,0 +1,13 @@ +{ + "raw_path": "/testpath", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test.execute-api.us-east-1.amazonaws.com", + "accept": "*/*" + }, + "query_string_parameters": {}, + "body": "", + "is_base64_encoded": false +} diff --git a/tests/functional/test_data_classes.py b/tests/functional/test_data_classes.py index b3a24b0865a..2469254d472 100644 --- a/tests/functional/test_data_classes.py +++ b/tests/functional/test_data_classes.py @@ -25,6 +25,7 @@ SESEvent, SNSEvent, SQSEvent, + VPCLatticeEvent ) from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import ( APIGatewayAuthorizerEventV2, @@ -2041,3 +2042,14 @@ def test_api_gateway_route_arn_parser(): details = parse_api_gateway_arn(arn) assert details.resource == "" assert details.arn == arn + "/" + + +def test_vpc_lattice_event(): + event = VPCLatticeEvent(load_event("vpcLatticeEvent.json")) + + assert event.raw_path == event["raw_path"] + assert event.method == event["method"] + assert event.headers == event["headers"] + assert event.query_string_parameters == event["query_string_parameters"] + assert event.body == event["body"] + assert event.is_base64_encoded == event["is_base64_encoded"] From d53d6a68beaa2ff1de9b18815e28398cf570938a Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Thu, 1 Jun 2023 07:12:11 -0400 Subject: [PATCH 05/12] fixing the host --- tests/events/vpcLatticeEvent.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/events/vpcLatticeEvent.json b/tests/events/vpcLatticeEvent.json index 4d9de9563f6..d8380202a1a 100644 --- a/tests/events/vpcLatticeEvent.json +++ b/tests/events/vpcLatticeEvent.json @@ -4,7 +4,7 @@ "headers": { "user_agent": "curl/7.64.1", "x-forwarded-for": "10.213.229.10", - "host": "test.execute-api.us-east-1.amazonaws.com", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", "accept": "*/*" }, "query_string_parameters": {}, From 8ae8382547c350907e4a89b183869317e73a3ca3 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Thu, 1 Jun 2023 08:32:07 -0400 Subject: [PATCH 06/12] updating documentation --- docs/utilities/data_classes.md | 65 ++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 04779ccf0f5..236f23f71c5 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -1121,6 +1121,71 @@ This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda do_something_with(record.body) ``` +### VPC Lattice + +The VPC Lattice service supports Lambda invocation for requests over both HTTP and HTTPS. The service sends an event in JSON format, and adds the `X-Forwarded-For` header to every request. The service also adds the X-Forwarded-Proto header to requests over HTTPS. + +The service Base64 encodes the body and sets isBase64Encoded to true, if the content-encoding header is present, and the content type is not one of the following: + +* `text/*` +* `application/json` +* `application/xml` +* `application/javascript` + +If the content-encoding header is not present, Base64 encoding depends on the content type. For the content types, `text/*`, `application/json`, `application/xml`, and `application/javascript`, the service sends the body as is and sets `is_base64_encoded` to `false`. + +=== "app.py" + + ```python + from aws_lambda_powertools.utilities.data_classes import event_source, VPCLatticeEvent + + @event_source(data_class=VPCLatticeEvent) + def lambda_handler(event: VPCLatticeEvent, context): + do_something_with(event.body) + + ``` + +=== "Lattice Excample Event" + + ```json + { + "raw_path": "/testpath", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "query_string_parameters": { + "key": "value" + }, + "body": "...", + "is_base64_encoded": false + } + ``` + +=== "Lattice Return Object" + + ```python + response = { + "isBase64Encoded": False, + "statusCode": 200, + headers: { + "Content-Type": "application/json" + }, + body: "Event Response to VPC Lattice 🔥🚀🔥" + } + + return response + ``` + +The response from your Lambda function must include the Base64 encoding status, status code, and headers. You can omit the body. + +To include a binary content in the body of the response, you must Base64 encode the content and set `isBase64Encoded` to `True`. The service decodes the content to retrieve the binary content and sends it to the client in the body of the HTTP response. + +The VPC Lattice service does not honor hop-by-hop headers, such as `Connection` or `Transfer-Encoding`. You can omit the `Content-Length` header because the service computes it before sending responses to clients. + ## Advanced ### Debugging From d57a500bef2b62bf8f8afa791bd43e5387e1ddcf Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Thu, 1 Jun 2023 08:36:46 -0400 Subject: [PATCH 07/12] spelling --- docs/utilities/data_classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 236f23f71c5..6e7ab1859ad 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -1145,7 +1145,7 @@ If the content-encoding header is not present, Base64 encoding depends on the co ``` -=== "Lattice Excample Event" +=== "Lattice Example Event" ```json { @@ -1172,7 +1172,7 @@ If the content-encoding header is not present, Base64 encoding depends on the co "isBase64Encoded": False, "statusCode": 200, headers: { - "Content-Type": "application/json" + "Content-Type": "application/text" }, body: "Event Response to VPC Lattice 🔥🚀🔥" } From ab5c1c4248b338d0843fa29bbfc5551331c25940 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Thu, 1 Jun 2023 16:36:02 -0400 Subject: [PATCH 08/12] missed a link --- docs/utilities/data_classes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 6e7ab1859ad..2fc356db143 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -102,6 +102,7 @@ Log Data Event for Troubleshooting | [SES](#ses) | `SESEvent` | | [SNS](#sns) | `SNSEvent` | | [SQS](#sqs) | `SQSEvent` | +| [VPC Lattice](#vpc-lattice) | `VPCLatticeEvent` | ???+ info The examples provided below are far from exhaustive - the data classes themselves are designed to provide a form of From 86aa432a255db49ffbbc3b4bc2382783b110ad99 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Wed, 7 Jun 2023 12:36:08 -0400 Subject: [PATCH 09/12] added properties --- .../utilities/data_classes/vpc_lattice.py | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py index da9a7ebb50a..e4388595c34 100644 --- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -1,15 +1,25 @@ -from typing import Dict +import base64 +from typing import Any, Dict, Optional from aws_lambda_powertools.utilities.data_classes.common import ( DictWrapper, + get_header_value ) + class VPCLatticeEvent(DictWrapper): @property def body(self) -> str: """The VPC Lattice body.""" return self["body"] + @property + def json_body(self) -> Any: + """Parses the submitted body as json""" + if self._json_data is None: + self._json_data = self._json_deserializer(self.decoded_body) + return self._json_data + @property def headers(self) -> Dict[str, str]: """The VPC Lattice event headers.""" @@ -20,6 +30,14 @@ def is_base64_encoded(self) -> bool: """A boolean flag to indicate if the applicable request payload is Base64-encode""" return self["is_base64_encoded"] + @property + def decoded_body(self) -> str: + """Dynamically base64 decode body as a str""" + body: str = self["body"] + if self.is_base64_encoded: + return base64.b64decode(body.encode()).decode() + return body + @property def method(self) -> str: """The VPC Lattice method used. Valid values include: DELETE, GET, HEAD, OPTIONS, PATCH, POST, and PUT.""" @@ -34,3 +52,40 @@ def query_string_parameters(self) -> Dict[str, str]: def raw_path(self) -> str: """The raw VPC Lattice request path.""" return self["raw_path"] + + def get_query_string_value(self, name: str, default_value: Optional[str] = None) -> Optional[str]: + """Get query string value by name + + Parameters + ---------- + name: str + Query string parameter name + default_value: str, optional + Default value if no value was found by name + Returns + ------- + str, optional + Query string parameter value + """ + params = self.query_string_parameters + return default_value if params is None else params.get(name, default_value) + + def get_header_value( + self, name: str, default_value: Optional[str] = None, case_sensitive: Optional[bool] = False + ) -> Optional[str]: + """Get header value by name + + Parameters + ---------- + name: str + Header name + default_value: str, optional + Default value if no value was found by name + case_sensitive: bool + Whether to use a case-sensitive look up + Returns + ------- + str, optional + Header value + """ + return get_header_value(self.headers, name, default_value, case_sensitive) From 07310a58fdf02e6072854d52a98c3c01192b8dd3 Mon Sep 17 00:00:00 2001 From: stephenbawks Date: Wed, 7 Jun 2023 12:47:57 -0400 Subject: [PATCH 10/12] test --- aws_lambda_powertools/utilities/data_classes/vpc_lattice.py | 1 + 1 file changed, 1 insertion(+) diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py index e4388595c34..eebb121e026 100644 --- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -89,3 +89,4 @@ def get_header_value( Header value """ return get_header_value(self.headers, name, default_value, case_sensitive) + From 75c4ef78085949622db79748b97128660bb524d5 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 8 Jun 2023 13:31:51 +0100 Subject: [PATCH 11/12] chore: tests + coverage + documentation --- .../utilities/data_classes/vpc_lattice.py | 3 +- docs/utilities/data_classes.md | 55 ++----------------- examples/event_sources/src/vpc_lattice.py | 19 +++++++ .../src/vpc_lattice_payload.json | 15 +++++ tests/events/vpcLatticeEvent.json | 8 ++- tests/functional/test_data_classes.py | 6 +- 6 files changed, 49 insertions(+), 57 deletions(-) create mode 100644 examples/event_sources/src/vpc_lattice.py create mode 100644 examples/event_sources/src/vpc_lattice_payload.json diff --git a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py index eebb121e026..4e503daf4ab 100644 --- a/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py +++ b/aws_lambda_powertools/utilities/data_classes/vpc_lattice.py @@ -3,7 +3,7 @@ from aws_lambda_powertools.utilities.data_classes.common import ( DictWrapper, - get_header_value + get_header_value, ) @@ -89,4 +89,3 @@ def get_header_value( Header value """ return get_header_value(self.headers, name, default_value, case_sensitive) - diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 2fc356db143..77e6c898e25 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -1124,69 +1124,22 @@ This example is based on the AWS Blog post [Introducing Amazon S3 Object Lambda ### VPC Lattice -The VPC Lattice service supports Lambda invocation for requests over both HTTP and HTTPS. The service sends an event in JSON format, and adds the `X-Forwarded-For` header to every request. The service also adds the X-Forwarded-Proto header to requests over HTTPS. +You can register your Lambda functions as targets within an Amazon VPC Lattice service network. By doing this, your Lambda function becomes a service within the network, and clients that have access to the VPC Lattice service network can call your service. -The service Base64 encodes the body and sets isBase64Encoded to true, if the content-encoding header is present, and the content type is not one of the following: - -* `text/*` -* `application/json` -* `application/xml` -* `application/javascript` - -If the content-encoding header is not present, Base64 encoding depends on the content type. For the content types, `text/*`, `application/json`, `application/xml`, and `application/javascript`, the service sends the body as is and sets `is_base64_encoded` to `false`. +[Click here](https://docs.aws.amazon.com/lambda/latest/dg/services-vpc-lattice.html){target="_blank"} for more information about using AWS Lambda with Amazon VPC Lattice. === "app.py" ```python - from aws_lambda_powertools.utilities.data_classes import event_source, VPCLatticeEvent - - @event_source(data_class=VPCLatticeEvent) - def lambda_handler(event: VPCLatticeEvent, context): - do_something_with(event.body) - + --8<-- "examples/event_sources/src/vpc_lattice.py" ``` === "Lattice Example Event" - ```json - { - "raw_path": "/testpath", - "method": "GET", - "headers": { - "user_agent": "curl/7.64.1", - "x-forwarded-for": "10.213.229.10", - "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", - "accept": "*/*" - }, - "query_string_parameters": { - "key": "value" - }, - "body": "...", - "is_base64_encoded": false - } - ``` - -=== "Lattice Return Object" - ```python - response = { - "isBase64Encoded": False, - "statusCode": 200, - headers: { - "Content-Type": "application/text" - }, - body: "Event Response to VPC Lattice 🔥🚀🔥" - } - - return response + --8<-- "examples/event_sources/src/vpc_lattice_payload.json" ``` -The response from your Lambda function must include the Base64 encoding status, status code, and headers. You can omit the body. - -To include a binary content in the body of the response, you must Base64 encode the content and set `isBase64Encoded` to `True`. The service decodes the content to retrieve the binary content and sends it to the client in the body of the HTTP response. - -The VPC Lattice service does not honor hop-by-hop headers, such as `Connection` or `Transfer-Encoding`. You can omit the `Content-Length` header because the service computes it before sending responses to clients. - ## Advanced ### Debugging diff --git a/examples/event_sources/src/vpc_lattice.py b/examples/event_sources/src/vpc_lattice.py new file mode 100644 index 00000000000..93291b5eb76 --- /dev/null +++ b/examples/event_sources/src/vpc_lattice.py @@ -0,0 +1,19 @@ +from aws_lambda_powertools import Logger +from aws_lambda_powertools.utilities.data_classes import VPCLatticeEvent, event_source +from aws_lambda_powertools.utilities.typing import LambdaContext + +logger = Logger() + + +@event_source(data_class=VPCLatticeEvent) +def lambda_handler(event: VPCLatticeEvent, context: LambdaContext): + logger.info(event.body) + + response = { + "isBase64Encoded": False, + "statusCode": 200, + "headers": {"Content-Type": "application/text"}, + "body": "Event Response to VPC Lattice 🔥🚀🔥", + } + + return response diff --git a/examples/event_sources/src/vpc_lattice_payload.json b/examples/event_sources/src/vpc_lattice_payload.json new file mode 100644 index 00000000000..0038592227a --- /dev/null +++ b/examples/event_sources/src/vpc_lattice_payload.json @@ -0,0 +1,15 @@ +{ + "raw_path": "/testpath", + "method": "GET", + "headers": { + "user_agent": "curl/7.64.1", + "x-forwarded-for": "10.213.229.10", + "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", + "accept": "*/*" + }, + "query_string_parameters": { + "order-id": "1" + }, + "body": "eyJ0ZXN0IjogImV2ZW50In0=", + "is_base64_encoded": true + } diff --git a/tests/events/vpcLatticeEvent.json b/tests/events/vpcLatticeEvent.json index d8380202a1a..936bfb22d1b 100644 --- a/tests/events/vpcLatticeEvent.json +++ b/tests/events/vpcLatticeEvent.json @@ -7,7 +7,9 @@ "host": "test-lambda-service-3908sdf9u3u.dkfjd93.vpc-lattice-svcs.us-east-2.on.aws", "accept": "*/*" }, - "query_string_parameters": {}, - "body": "", - "is_base64_encoded": false + "query_string_parameters": { + "order-id": "1" + }, + "body": "eyJ0ZXN0IjogImV2ZW50In0=", + "is_base64_encoded": true } diff --git a/tests/functional/test_data_classes.py b/tests/functional/test_data_classes.py index 2469254d472..23f4b18e53d 100644 --- a/tests/functional/test_data_classes.py +++ b/tests/functional/test_data_classes.py @@ -25,7 +25,7 @@ SESEvent, SNSEvent, SQSEvent, - VPCLatticeEvent + VPCLatticeEvent, ) from aws_lambda_powertools.utilities.data_classes.api_gateway_authorizer_event import ( APIGatewayAuthorizerEventV2, @@ -2048,6 +2048,10 @@ def test_vpc_lattice_event(): event = VPCLatticeEvent(load_event("vpcLatticeEvent.json")) assert event.raw_path == event["raw_path"] + assert event.get_query_string_value("order-id") == "1" + assert event.get_header_value("user_agent") == "curl/7.64.1" + assert event.decoded_body == '{"test": "event"}' + assert event.json_body == {"test": "event"} assert event.method == event["method"] assert event.headers == event["headers"] assert event.query_string_parameters == event["query_string_parameters"] From 0c208f262f65b28cfb47e2a011f44b86c094a7b2 Mon Sep 17 00:00:00 2001 From: Leandro Damascena Date: Thu, 8 Jun 2023 13:35:12 +0100 Subject: [PATCH 12/12] chore: documentation --- docs/utilities/data_classes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/utilities/data_classes.md b/docs/utilities/data_classes.md index 77e6c898e25..cc6ba30a335 100644 --- a/docs/utilities/data_classes.md +++ b/docs/utilities/data_classes.md @@ -1130,13 +1130,13 @@ You can register your Lambda functions as targets within an Amazon VPC Lattice s === "app.py" - ```python + ```python hl_lines="2 8" --8<-- "examples/event_sources/src/vpc_lattice.py" ``` === "Lattice Example Event" - ```python + ```json --8<-- "examples/event_sources/src/vpc_lattice_payload.json" ```