We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Make sure we can re-run pipelines
### Enabler

So that we can continue working when a pipeline fails for spurious reasons, we want to make sure we can re-run them.

#### Acceptance Criteria

- [ ] Re-running a pipeline does not cause it to fail unconditionally.

#### Additional context

From build:

> CREATE_FAILED        | AWS::Logs::LogGroup              | api/api-user-log (apiapiuserlog714734B6) Resource handler returned message: "Resource of type 'AWS::Logs::LogGroup' with identifier '{"/properties/LogGroupName":"ci1953438111-geostore-cloudtrail-api"}' already exists." (RequestToken: …, HandlerErrorCode: AlreadyExists)

#### Tasks

<!-- Tasks needed to complete this enabler -->

- [ ] ...
- [ ] ...

#### Definition of Ready

- [ ] This story is **ready** to work on
  - [ ] Negotiable (team can decide how to design and implement)
  - [ ] Valuable (from a user perspective)
  - [ ] Estimate value applied (agreed by team)
  - [ ] Small (so as to fit within an iteration)
  - [ ] Testable (in principle, even if there isn't a test for it yet)
  - [ ] Environments are ready to meet definition of done
  - [ ] Resources required to implement will be ready
  - [ ] Everyone understands and agrees with the tasks to complete the story
  - [ ] Release value (e.g. Iteration 3) applied
  - [ ] Sprint value (e.g. Aug 1 - Aug 15) applied

#### Definition of Done

- [ ] This story is **done**:
  - [ ] Acceptance criteria completed
  - [ ] Automated tests are passing
  - [ ] Code is peer reviewed and pushed to master
  - [ ] Deployed successfully to test environment
  - [ ] Checked against [CODING guidelines](https://github.com/linz/geostore/blob/master/CODING.md)
  - [ ] Relevant new tasks are added to backlog and communicated to the team
  - [ ] Important decisions recorded in the issue ticket
  - [ ] Readme/Changelog/Diagrams are updated
  - [ ] Product Owner has approved acceptance criteria as complete
  - [ ] Meets non-functional requirements:
    - [ ] Scalability (data): Can scale to 300TB of data and 100,000,000 files and ability to
          increase 10% every year
    - [ ] Scability (users): Can scale to 100 concurrent users
    - [ ] Cost: Data can be stored at < 0.5 NZD per GB per year
    - [ ] Performance: A large dataset (500 GB and 50,000 files - e.g. Akl aerial imagery) can be
          validated, imported and stored within 24 hours
    - [ ] Accessibility: Can be used from LINZ networks and the public internet
    - [ ] Availability: System available 24 hours a day and 7 days a week, this does not include
          maintenance windows < 4 hours and does not include operational support
    - [ ] Recoverability: RPO of fully imported datasets < 4 hours, RTO of a single 3 TB dataset <
          12 hours

<!-- Please add one or more of these labels: 'spike', 'refactor', 'architecture', 'infrastructure', 'compliance' -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `infrastructure/constructs/api.py`
Content:
```
1 from aws_cdk import (
2     aws_cloudtrail,
3     aws_iam,
4     aws_lambda_python,
5     aws_logs,
6     aws_s3,
7     aws_sqs,
8     aws_ssm,
9     aws_stepfunctions,
10 )
11 from aws_cdk.core import Construct, RemovalPolicy, Tags
12 
13 from geostore.resources import Resource
14 
15 from .common import grant_parameter_read_access
16 from .lambda_endpoint import LambdaEndpoint
17 from .roles import MAX_SESSION_DURATION
18 from .s3_policy import ALLOW_DESCRIBE_ANY_S3_JOB
19 from .table import Table
20 
21 
22 class API(Construct):
23     def __init__(  # pylint: disable=too-many-arguments,too-many-locals
24         self,
25         scope: Construct,
26         stack_id: str,
27         *,
28         botocore_lambda_layer: aws_lambda_python.PythonLayerVersion,
29         datasets_table: Table,
30         env_name: str,
31         principal: aws_iam.PrincipalBase,
32         state_machine: aws_stepfunctions.StateMachine,
33         state_machine_parameter: aws_ssm.StringParameter,
34         sqs_queue: aws_sqs.Queue,
35         sqs_queue_parameter: aws_ssm.StringParameter,
36         storage_bucket: aws_s3.Bucket,
37         validation_results_table: Table,
38     ) -> None:
39         super().__init__(scope, stack_id)
40 
41         ############################################################################################
42         # ### API ENDPOINTS ########################################################################
43         ############################################################################################
44 
45         api_users_role = aws_iam.Role(
46             self,
47             "api-users-role",
48             role_name=Resource.API_USERS_ROLE_NAME.resource_name,
49             assumed_by=principal,  # type: ignore[arg-type]
50             max_session_duration=MAX_SESSION_DURATION,
51         )
52 
53         datasets_endpoint_lambda = LambdaEndpoint(
54             self,
55             "datasets",
56             package_name="datasets",
57             env_name=env_name,
58             users_role=api_users_role,
59             botocore_lambda_layer=botocore_lambda_layer,
60         )
61 
62         dataset_versions_endpoint_lambda = LambdaEndpoint(
63             self,
64             "dataset-versions",
65             package_name="dataset_versions",
66             env_name=env_name,
67             users_role=api_users_role,
68             botocore_lambda_layer=botocore_lambda_layer,
69         )
70 
71         state_machine.grant_start_execution(dataset_versions_endpoint_lambda)
72 
73         storage_bucket.grant_read_write(datasets_endpoint_lambda)
74 
75         sqs_queue.grant_send_messages(datasets_endpoint_lambda)
76 
77         for function in [datasets_endpoint_lambda, dataset_versions_endpoint_lambda]:
78             datasets_table.grant_read_write_data(function)
79             datasets_table.grant(function, "dynamodb:DescribeTable")  # required by pynamodb
80 
81         import_status_endpoint_lambda = LambdaEndpoint(
82             self,
83             "import-status",
84             package_name="import_status",
85             env_name=env_name,
86             users_role=api_users_role,
87             botocore_lambda_layer=botocore_lambda_layer,
88         )
89 
90         validation_results_table.grant_read_data(import_status_endpoint_lambda)
91         validation_results_table.grant(
92             import_status_endpoint_lambda, "dynamodb:DescribeTable"
93         )  # required by pynamodb
94 
95         state_machine.grant_read(import_status_endpoint_lambda)
96         import_status_endpoint_lambda.add_to_role_policy(ALLOW_DESCRIBE_ANY_S3_JOB)
97 
98         grant_parameter_read_access(
99             {
100                 datasets_table.name_parameter: [
101                     datasets_endpoint_lambda,
102                     dataset_versions_endpoint_lambda,
103                 ],
104                 validation_results_table.name_parameter: [import_status_endpoint_lambda],
105                 state_machine_parameter: [dataset_versions_endpoint_lambda],
106                 sqs_queue_parameter: [datasets_endpoint_lambda],
107             }
108         )
109 
110         trail_bucket = aws_s3.Bucket(
111             self,
112             "cloudtrail-bucket",
113             bucket_name=Resource.CLOUDTRAIL_BUCKET_NAME.resource_name,
114             access_control=aws_s3.BucketAccessControl.PRIVATE,
115             block_public_access=aws_s3.BlockPublicAccess.BLOCK_ALL,
116             auto_delete_objects=True,
117             removal_policy=RemovalPolicy.DESTROY,
118         )
119 
120         trail = aws_cloudtrail.Trail(
121             self,
122             "cloudtrail",
123             send_to_cloud_watch_logs=True,
124             bucket=trail_bucket,  # type: ignore[arg-type]
125             cloud_watch_log_group=aws_logs.LogGroup(
126                 self,
127                 "api-user-log",
128                 log_group_name=Resource.CLOUDTRAIL_LOG_GROUP_NAME.resource_name,
129             ),  # type: ignore[arg-type]
130         )
131         trail.add_lambda_event_selector(
132             [
133                 import_status_endpoint_lambda,
134                 dataset_versions_endpoint_lambda,
135                 datasets_endpoint_lambda,
136             ],
137             include_management_events=False,
138         )
139 
140         ############################################################################################
141         # ### S3 API ###############################################################################
142         ############################################################################################
143 
144         s3_users_role = aws_iam.Role(
145             self,
146             "s3-users-role",
147             role_name=Resource.S3_USERS_ROLE_NAME.resource_name,
148             assumed_by=principal,  # type: ignore[arg-type]
149             max_session_duration=MAX_SESSION_DURATION,
150         )
151         storage_bucket.grant_read(s3_users_role)  # type: ignore[arg-type]
152 
153         Tags.of(self).add("ApplicationLayer", "api")  # type: ignore[arg-type]
154
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/infrastructure/constructs/api.py b/infrastructure/constructs/api.py
--- a/infrastructure/constructs/api.py
+++ b/infrastructure/constructs/api.py
@@ -14,6 +14,7 @@
 
 from .common import grant_parameter_read_access
 from .lambda_endpoint import LambdaEndpoint
+from .removal_policy import REMOVAL_POLICY
 from .roles import MAX_SESSION_DURATION
 from .s3_policy import ALLOW_DESCRIBE_ANY_S3_JOB
 from .table import Table
@@ -126,6 +127,7 @@
                 self,
                 "api-user-log",
                 log_group_name=Resource.CLOUDTRAIL_LOG_GROUP_NAME.resource_name,
+                removal_policy=REMOVAL_POLICY,
             ),  # type: ignore[arg-type]
         )
         trail.add_lambda_event_selector(

{"golden_diff": "diff --git a/infrastructure/constructs/api.py b/infrastructure/constructs/api.py\n--- a/infrastructure/constructs/api.py\n+++ b/infrastructure/constructs/api.py\n@@ -14,6 +14,7 @@\n \n from .common import grant_parameter_read_access\n from .lambda_endpoint import LambdaEndpoint\n+from .removal_policy import REMOVAL_POLICY\n from .roles import MAX_SESSION_DURATION\n from .s3_policy import ALLOW_DESCRIBE_ANY_S3_JOB\n from .table import Table\n@@ -126,6 +127,7 @@\n                 self,\n                 \"api-user-log\",\n                 log_group_name=Resource.CLOUDTRAIL_LOG_GROUP_NAME.resource_name,\n+                removal_policy=REMOVAL_POLICY,\n             ),  # type: ignore[arg-type]\n         )\n         trail.add_lambda_event_selector(\n", "issue": "Make sure we can re-run pipelines\n### Enabler\r\n\r\nSo that we can continue working when a pipeline fails for spurious reasons, we want to make sure we can re-run them.\r\n\r\n#### Acceptance Criteria\r\n\r\n- [ ] Re-running a pipeline does not cause it to fail unconditionally.\r\n\r\n#### Additional context\r\n\r\nFrom build:\r\n\r\n> CREATE_FAILED        | AWS::Logs::LogGroup              | api/api-user-log (apiapiuserlog714734B6) Resource handler returned message: \"Resource of type 'AWS::Logs::LogGroup' with identifier '{\"/properties/LogGroupName\":\"ci1953438111-geostore-cloudtrail-api\"}' already exists.\" (RequestToken: \u2026, HandlerErrorCode: AlreadyExists)\r\n\r\n#### Tasks\r\n\r\n<!-- Tasks needed to complete this enabler -->\r\n\r\n- [ ] ...\r\n- [ ] ...\r\n\r\n#### Definition of Ready\r\n\r\n- [ ] This story is **ready** to work on\r\n  - [ ] Negotiable (team can decide how to design and implement)\r\n  - [ ] Valuable (from a user perspective)\r\n  - [ ] Estimate value applied (agreed by team)\r\n  - [ ] Small (so as to fit within an iteration)\r\n  - [ ] Testable (in principle, even if there isn't a test for it yet)\r\n  - [ ] Environments are ready to meet definition of done\r\n  - [ ] Resources required to implement will be ready\r\n  - [ ] Everyone understands and agrees with the tasks to complete the story\r\n  - [ ] Release value (e.g. Iteration 3) applied\r\n  - [ ] Sprint value (e.g. Aug 1 - Aug 15) applied\r\n\r\n#### Definition of Done\r\n\r\n- [ ] This story is **done**:\r\n  - [ ] Acceptance criteria completed\r\n  - [ ] Automated tests are passing\r\n  - [ ] Code is peer reviewed and pushed to master\r\n  - [ ] Deployed successfully to test environment\r\n  - [ ] Checked against [CODING guidelines](https://github.com/linz/geostore/blob/master/CODING.md)\r\n  - [ ] Relevant new tasks are added to backlog and communicated to the team\r\n  - [ ] Important decisions recorded in the issue ticket\r\n  - [ ] Readme/Changelog/Diagrams are updated\r\n  - [ ] Product Owner has approved acceptance criteria as complete\r\n  - [ ] Meets non-functional requirements:\r\n    - [ ] Scalability (data): Can scale to 300TB of data and 100,000,000 files and ability to\r\n          increase 10% every year\r\n    - [ ] Scability (users): Can scale to 100 concurrent users\r\n    - [ ] Cost: Data can be stored at < 0.5 NZD per GB per year\r\n    - [ ] Performance: A large dataset (500 GB and 50,000 files - e.g. Akl aerial imagery) can be\r\n          validated, imported and stored within 24 hours\r\n    - [ ] Accessibility: Can be used from LINZ networks and the public internet\r\n    - [ ] Availability: System available 24 hours a day and 7 days a week, this does not include\r\n          maintenance windows < 4 hours and does not include operational support\r\n    - [ ] Recoverability: RPO of fully imported datasets < 4 hours, RTO of a single 3 TB dataset <\r\n          12 hours\r\n\r\n<!-- Please add one or more of these labels: 'spike', 'refactor', 'architecture', 'infrastructure', 'compliance' -->\r\n\n", "before_files": [{"content": "from aws_cdk import (\n    aws_cloudtrail,\n    aws_iam,\n    aws_lambda_python,\n    aws_logs,\n    aws_s3,\n    aws_sqs,\n    aws_ssm,\n    aws_stepfunctions,\n)\nfrom aws_cdk.core import Construct, RemovalPolicy, Tags\n\nfrom geostore.resources import Resource\n\nfrom .common import grant_parameter_read_access\nfrom .lambda_endpoint import LambdaEndpoint\nfrom .roles import MAX_SESSION_DURATION\nfrom .s3_policy import ALLOW_DESCRIBE_ANY_S3_JOB\nfrom .table import Table\n\n\nclass API(Construct):\n    def __init__(  # pylint: disable=too-many-arguments,too-many-locals\n        self,\n        scope: Construct,\n        stack_id: str,\n        *,\n        botocore_lambda_layer: aws_lambda_python.PythonLayerVersion,\n        datasets_table: Table,\n        env_name: str,\n        principal: aws_iam.PrincipalBase,\n        state_machine: aws_stepfunctions.StateMachine,\n        state_machine_parameter: aws_ssm.StringParameter,\n        sqs_queue: aws_sqs.Queue,\n        sqs_queue_parameter: aws_ssm.StringParameter,\n        storage_bucket: aws_s3.Bucket,\n        validation_results_table: Table,\n    ) -> None:\n        super().__init__(scope, stack_id)\n\n        ############################################################################################\n        # ### API ENDPOINTS ########################################################################\n        ############################################################################################\n\n        api_users_role = aws_iam.Role(\n            self,\n            \"api-users-role\",\n            role_name=Resource.API_USERS_ROLE_NAME.resource_name,\n            assumed_by=principal,  # type: ignore[arg-type]\n            max_session_duration=MAX_SESSION_DURATION,\n        )\n\n        datasets_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"datasets\",\n            package_name=\"datasets\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        dataset_versions_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"dataset-versions\",\n            package_name=\"dataset_versions\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        state_machine.grant_start_execution(dataset_versions_endpoint_lambda)\n\n        storage_bucket.grant_read_write(datasets_endpoint_lambda)\n\n        sqs_queue.grant_send_messages(datasets_endpoint_lambda)\n\n        for function in [datasets_endpoint_lambda, dataset_versions_endpoint_lambda]:\n            datasets_table.grant_read_write_data(function)\n            datasets_table.grant(function, \"dynamodb:DescribeTable\")  # required by pynamodb\n\n        import_status_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"import-status\",\n            package_name=\"import_status\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        validation_results_table.grant_read_data(import_status_endpoint_lambda)\n        validation_results_table.grant(\n            import_status_endpoint_lambda, \"dynamodb:DescribeTable\"\n        )  # required by pynamodb\n\n        state_machine.grant_read(import_status_endpoint_lambda)\n        import_status_endpoint_lambda.add_to_role_policy(ALLOW_DESCRIBE_ANY_S3_JOB)\n\n        grant_parameter_read_access(\n            {\n                datasets_table.name_parameter: [\n                    datasets_endpoint_lambda,\n                    dataset_versions_endpoint_lambda,\n                ],\n                validation_results_table.name_parameter: [import_status_endpoint_lambda],\n                state_machine_parameter: [dataset_versions_endpoint_lambda],\n                sqs_queue_parameter: [datasets_endpoint_lambda],\n            }\n        )\n\n        trail_bucket = aws_s3.Bucket(\n            self,\n            \"cloudtrail-bucket\",\n            bucket_name=Resource.CLOUDTRAIL_BUCKET_NAME.resource_name,\n            access_control=aws_s3.BucketAccessControl.PRIVATE,\n            block_public_access=aws_s3.BlockPublicAccess.BLOCK_ALL,\n            auto_delete_objects=True,\n            removal_policy=RemovalPolicy.DESTROY,\n        )\n\n        trail = aws_cloudtrail.Trail(\n            self,\n            \"cloudtrail\",\n            send_to_cloud_watch_logs=True,\n            bucket=trail_bucket,  # type: ignore[arg-type]\n            cloud_watch_log_group=aws_logs.LogGroup(\n                self,\n                \"api-user-log\",\n                log_group_name=Resource.CLOUDTRAIL_LOG_GROUP_NAME.resource_name,\n            ),  # type: ignore[arg-type]\n        )\n        trail.add_lambda_event_selector(\n            [\n                import_status_endpoint_lambda,\n                dataset_versions_endpoint_lambda,\n                datasets_endpoint_lambda,\n            ],\n            include_management_events=False,\n        )\n\n        ############################################################################################\n        # ### S3 API ###############################################################################\n        ############################################################################################\n\n        s3_users_role = aws_iam.Role(\n            self,\n            \"s3-users-role\",\n            role_name=Resource.S3_USERS_ROLE_NAME.resource_name,\n            assumed_by=principal,  # type: ignore[arg-type]\n            max_session_duration=MAX_SESSION_DURATION,\n        )\n        storage_bucket.grant_read(s3_users_role)  # type: ignore[arg-type]\n\n        Tags.of(self).add(\"ApplicationLayer\", \"api\")  # type: ignore[arg-type]\n", "path": "infrastructure/constructs/api.py"}], "after_files": [{"content": "from aws_cdk import (\n    aws_cloudtrail,\n    aws_iam,\n    aws_lambda_python,\n    aws_logs,\n    aws_s3,\n    aws_sqs,\n    aws_ssm,\n    aws_stepfunctions,\n)\nfrom aws_cdk.core import Construct, RemovalPolicy, Tags\n\nfrom geostore.resources import Resource\n\nfrom .common import grant_parameter_read_access\nfrom .lambda_endpoint import LambdaEndpoint\nfrom .removal_policy import REMOVAL_POLICY\nfrom .roles import MAX_SESSION_DURATION\nfrom .s3_policy import ALLOW_DESCRIBE_ANY_S3_JOB\nfrom .table import Table\n\n\nclass API(Construct):\n    def __init__(  # pylint: disable=too-many-arguments,too-many-locals\n        self,\n        scope: Construct,\n        stack_id: str,\n        *,\n        botocore_lambda_layer: aws_lambda_python.PythonLayerVersion,\n        datasets_table: Table,\n        env_name: str,\n        principal: aws_iam.PrincipalBase,\n        state_machine: aws_stepfunctions.StateMachine,\n        state_machine_parameter: aws_ssm.StringParameter,\n        sqs_queue: aws_sqs.Queue,\n        sqs_queue_parameter: aws_ssm.StringParameter,\n        storage_bucket: aws_s3.Bucket,\n        validation_results_table: Table,\n    ) -> None:\n        super().__init__(scope, stack_id)\n\n        ############################################################################################\n        # ### API ENDPOINTS ########################################################################\n        ############################################################################################\n\n        api_users_role = aws_iam.Role(\n            self,\n            \"api-users-role\",\n            role_name=Resource.API_USERS_ROLE_NAME.resource_name,\n            assumed_by=principal,  # type: ignore[arg-type]\n            max_session_duration=MAX_SESSION_DURATION,\n        )\n\n        datasets_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"datasets\",\n            package_name=\"datasets\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        dataset_versions_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"dataset-versions\",\n            package_name=\"dataset_versions\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        state_machine.grant_start_execution(dataset_versions_endpoint_lambda)\n\n        storage_bucket.grant_read_write(datasets_endpoint_lambda)\n\n        sqs_queue.grant_send_messages(datasets_endpoint_lambda)\n\n        for function in [datasets_endpoint_lambda, dataset_versions_endpoint_lambda]:\n            datasets_table.grant_read_write_data(function)\n            datasets_table.grant(function, \"dynamodb:DescribeTable\")  # required by pynamodb\n\n        import_status_endpoint_lambda = LambdaEndpoint(\n            self,\n            \"import-status\",\n            package_name=\"import_status\",\n            env_name=env_name,\n            users_role=api_users_role,\n            botocore_lambda_layer=botocore_lambda_layer,\n        )\n\n        validation_results_table.grant_read_data(import_status_endpoint_lambda)\n        validation_results_table.grant(\n            import_status_endpoint_lambda, \"dynamodb:DescribeTable\"\n        )  # required by pynamodb\n\n        state_machine.grant_read(import_status_endpoint_lambda)\n        import_status_endpoint_lambda.add_to_role_policy(ALLOW_DESCRIBE_ANY_S3_JOB)\n\n        grant_parameter_read_access(\n            {\n                datasets_table.name_parameter: [\n                    datasets_endpoint_lambda,\n                    dataset_versions_endpoint_lambda,\n                ],\n                validation_results_table.name_parameter: [import_status_endpoint_lambda],\n                state_machine_parameter: [dataset_versions_endpoint_lambda],\n                sqs_queue_parameter: [datasets_endpoint_lambda],\n            }\n        )\n\n        trail_bucket = aws_s3.Bucket(\n            self,\n            \"cloudtrail-bucket\",\n            bucket_name=Resource.CLOUDTRAIL_BUCKET_NAME.resource_name,\n            access_control=aws_s3.BucketAccessControl.PRIVATE,\n            block_public_access=aws_s3.BlockPublicAccess.BLOCK_ALL,\n            auto_delete_objects=True,\n            removal_policy=RemovalPolicy.DESTROY,\n        )\n\n        trail = aws_cloudtrail.Trail(\n            self,\n            \"cloudtrail\",\n            send_to_cloud_watch_logs=True,\n            bucket=trail_bucket,  # type: ignore[arg-type]\n            cloud_watch_log_group=aws_logs.LogGroup(\n                self,\n                \"api-user-log\",\n                log_group_name=Resource.CLOUDTRAIL_LOG_GROUP_NAME.resource_name,\n                removal_policy=REMOVAL_POLICY,\n            ),  # type: ignore[arg-type]\n        )\n        trail.add_lambda_event_selector(\n            [\n                import_status_endpoint_lambda,\n                dataset_versions_endpoint_lambda,\n                datasets_endpoint_lambda,\n            ],\n            include_management_events=False,\n        )\n\n        ############################################################################################\n        # ### S3 API ###############################################################################\n        ############################################################################################\n\n        s3_users_role = aws_iam.Role(\n            self,\n            \"s3-users-role\",\n            role_name=Resource.S3_USERS_ROLE_NAME.resource_name,\n            assumed_by=principal,  # type: ignore[arg-type]\n            max_session_duration=MAX_SESSION_DURATION,\n        )\n        storage_bucket.grant_read(s3_users_role)  # type: ignore[arg-type]\n\n        Tags.of(self).add(\"ApplicationLayer\", \"api\")  # type: ignore[arg-type]\n", "path": "infrastructure/constructs/api.py"}]}