@aws/nx-plugin-mcp 1.0.0-rc.81 → 1.0.0-rc.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -70,42 +70,41 @@ table.grantReadWriteData(myAgent);
70
70
  </Fragment>
71
71
  <Fragment slot="terraform">
72
72
 
73
+ Grant the agent's runtime role access to the table and its KMS encryption key via `additional_iam_policy_statements`:
74
+
73
75
  ```hcl title="packages/infra/src/main.tf"
74
76
  module "my_table" {
75
77
  source = "../../common/terraform/src/app/dynamodb/my-table"
76
78
  }
77
79
 
78
- resource "aws_iam_role_policy" "dynamodb_access" {
79
- role = module.my_agent.lambda_role_name
80
-
81
- policy = jsonencode({
82
- Version = "2012-10-17"
83
- Statement = [
84
- {
85
- Effect = "Allow"
86
- Action = [
87
- "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
88
- "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
89
- "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
90
- ]
91
- Resource = [
92
- module.my_table.table_arn,
93
- "${module.my_table.table_arn}/index/*",
94
- ]
95
- },
96
- {
97
- Effect = "Allow"
98
- Action = [
99
- "kms:Encrypt",
100
- "kms:Decrypt",
101
- "kms:ReEncrypt*",
102
- "kms:GenerateDataKey*",
103
- "kms:DescribeKey"
104
- ]
105
- Resource = [module.my_table.kms_key_arn]
106
- },
107
- ]
108
- })
80
+ module "my_agent" {
81
+ source = "../../common/terraform/src/app/agents/my-agent"
82
+
83
+ additional_iam_policy_statements = [
84
+ {
85
+ Effect = "Allow"
86
+ Action = [
87
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
88
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
89
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
90
+ ]
91
+ Resource = [
92
+ module.my_table.table_arn,
93
+ "${module.my_table.table_arn}/index/*",
94
+ ]
95
+ },
96
+ {
97
+ Effect = "Allow"
98
+ Action = [
99
+ "kms:Encrypt",
100
+ "kms:Decrypt",
101
+ "kms:ReEncrypt*",
102
+ "kms:GenerateDataKey*",
103
+ "kms:DescribeKey",
104
+ ]
105
+ Resource = [module.my_table.kms_key_arn]
106
+ },
107
+ ]
109
108
  }
110
109
  ```
111
110
  </Fragment>
@@ -146,16 +146,7 @@ resource "aws_vpc_security_group_egress_rule" "agent_to_database" {
146
146
  }
147
147
  ```
148
148
 
149
- `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
150
-
151
- ```hcl title="packages/infra/src/main.tf"
152
- module "runtime_config_appconfig" {
153
- source = "../../common/terraform/src/core/runtime-config/appconfig"
154
-
155
- application_name = "my-app-runtime-config"
156
- namespaces = ["connection", "agentcore", "database"]
157
- }
158
- ```
149
+ `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
159
150
 
160
151
  </Fragment>
161
152
  </Infrastructure>
@@ -163,16 +163,7 @@ resource "aws_vpc_security_group_egress_rule" "api_to_database" {
163
163
 
164
164
  Deploy the API Lambda functions into **private subnets with egress**, not private isolated subnets. `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module — passing them sets `RUNTIME_CONFIG_APP_ID` on the Lambda functions and grants them read access to the application.
165
165
 
166
- The AppConfig application must expose the `database` namespace so the database module's runtime configuration entry is deployed. Include it in the `namespaces` when instantiating the `runtime-config/appconfig` module:
167
-
168
- ```hcl title="packages/infra/src/main.tf"
169
- module "runtime_config_appconfig" {
170
- source = "../../common/terraform/src/core/runtime-config/appconfig"
171
-
172
- application_name = "my-app-runtime-config"
173
- namespaces = ["connection", "agentcore", "database"]
174
- }
175
- ```
166
+ The AppConfig application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
176
167
 
177
168
  </Fragment>
178
169
  </Infrastructure>
@@ -70,42 +70,41 @@ table.grantReadWriteData(myMcpServer);
70
70
  </Fragment>
71
71
  <Fragment slot="terraform">
72
72
 
73
+ Grant the MCP server's runtime role access to the table and its KMS encryption key via `additional_iam_policy_statements`:
74
+
73
75
  ```hcl title="packages/infra/src/main.tf"
74
76
  module "my_table" {
75
77
  source = "../../common/terraform/src/app/dynamodb/my-table"
76
78
  }
77
79
 
78
- resource "aws_iam_role_policy" "dynamodb_access" {
79
- role = module.my_mcp_server.lambda_role_name
80
-
81
- policy = jsonencode({
82
- Version = "2012-10-17"
83
- Statement = [
84
- {
85
- Effect = "Allow"
86
- Action = [
87
- "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
88
- "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
89
- "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
90
- ]
91
- Resource = [
92
- module.my_table.table_arn,
93
- "${module.my_table.table_arn}/index/*",
94
- ]
95
- },
96
- {
97
- Effect = "Allow"
98
- Action = [
99
- "kms:Encrypt",
100
- "kms:Decrypt",
101
- "kms:ReEncrypt*",
102
- "kms:GenerateDataKey*",
103
- "kms:DescribeKey"
104
- ]
105
- Resource = [module.my_table.kms_key_arn]
106
- },
107
- ]
108
- })
80
+ module "my_mcp_server" {
81
+ source = "../../common/terraform/src/app/mcp-servers/my-mcp-server"
82
+
83
+ additional_iam_policy_statements = [
84
+ {
85
+ Effect = "Allow"
86
+ Action = [
87
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
88
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
89
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
90
+ ]
91
+ Resource = [
92
+ module.my_table.table_arn,
93
+ "${module.my_table.table_arn}/index/*",
94
+ ]
95
+ },
96
+ {
97
+ Effect = "Allow"
98
+ Action = [
99
+ "kms:Encrypt",
100
+ "kms:Decrypt",
101
+ "kms:ReEncrypt*",
102
+ "kms:GenerateDataKey*",
103
+ "kms:DescribeKey",
104
+ ]
105
+ Resource = [module.my_table.kms_key_arn]
106
+ },
107
+ ]
109
108
  }
110
109
  ```
111
110
  </Fragment>
@@ -155,16 +155,7 @@ resource "aws_vpc_security_group_egress_rule" "mcp_server_to_database" {
155
155
  }
156
156
  ```
157
157
 
158
- `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
159
-
160
- ```hcl title="packages/infra/src/main.tf"
161
- module "runtime_config_appconfig" {
162
- source = "../../common/terraform/src/core/runtime-config/appconfig"
163
-
164
- application_name = "my-app-runtime-config"
165
- namespaces = ["connection", "agentcore", "database"]
166
- }
167
- ```
158
+ `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
168
159
 
169
160
  </Fragment>
170
161
  </Infrastructure>
@@ -82,42 +82,41 @@ table.grantReadWriteData(myAgent);
82
82
  </Fragment>
83
83
  <Fragment slot="terraform">
84
84
 
85
+ Grant the agent's runtime role access to the table and its KMS encryption key via `additional_iam_policy_statements`:
86
+
85
87
  ```hcl title="packages/infra/src/main.tf"
86
88
  module "my_table" {
87
89
  source = "../../common/terraform/src/app/dynamodb/my-table"
88
90
  }
89
91
 
90
- resource "aws_iam_role_policy" "dynamodb_access" {
91
- role = module.my_agent.lambda_role_name
92
-
93
- policy = jsonencode({
94
- Version = "2012-10-17"
95
- Statement = [
96
- {
97
- Effect = "Allow"
98
- Action = [
99
- "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
100
- "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
101
- "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
102
- ]
103
- Resource = [
104
- module.my_table.table_arn,
105
- "${module.my_table.table_arn}/index/*",
106
- ]
107
- },
108
- {
109
- Effect = "Allow"
110
- Action = [
111
- "kms:Encrypt",
112
- "kms:Decrypt",
113
- "kms:ReEncrypt*",
114
- "kms:GenerateDataKey*",
115
- "kms:DescribeKey"
116
- ]
117
- Resource = [module.my_table.kms_key_arn]
118
- },
119
- ]
120
- })
92
+ module "my_agent" {
93
+ source = "../../common/terraform/src/app/agents/my-agent"
94
+
95
+ additional_iam_policy_statements = [
96
+ {
97
+ Effect = "Allow"
98
+ Action = [
99
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
100
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
101
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
102
+ ]
103
+ Resource = [
104
+ module.my_table.table_arn,
105
+ "${module.my_table.table_arn}/index/*",
106
+ ]
107
+ },
108
+ {
109
+ Effect = "Allow"
110
+ Action = [
111
+ "kms:Encrypt",
112
+ "kms:Decrypt",
113
+ "kms:ReEncrypt*",
114
+ "kms:GenerateDataKey*",
115
+ "kms:DescribeKey",
116
+ ]
117
+ Resource = [module.my_table.kms_key_arn]
118
+ },
119
+ ]
121
120
  }
122
121
  ```
123
122
  </Fragment>
@@ -161,16 +161,7 @@ resource "aws_vpc_security_group_egress_rule" "agent_to_database" {
161
161
  }
162
162
  ```
163
163
 
164
- `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
165
-
166
- ```hcl title="packages/infra/src/main.tf"
167
- module "runtime_config_appconfig" {
168
- source = "../../common/terraform/src/core/runtime-config/appconfig"
169
-
170
- application_name = "my-app-runtime-config"
171
- namespaces = ["connection", "agentcore", "database"]
172
- }
173
- ```
164
+ `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
174
165
 
175
166
  </Fragment>
176
167
  </Infrastructure>
@@ -79,42 +79,41 @@ table.grantReadWriteData(myMcpServer);
79
79
  </Fragment>
80
80
  <Fragment slot="terraform">
81
81
 
82
+ Grant the MCP server's runtime role access to the table and its KMS encryption key via `additional_iam_policy_statements`:
83
+
82
84
  ```hcl title="packages/infra/src/main.tf"
83
85
  module "my_table" {
84
86
  source = "../../common/terraform/src/app/dynamodb/my-table"
85
87
  }
86
88
 
87
- resource "aws_iam_role_policy" "dynamodb_access" {
88
- role = module.my_mcp_server.lambda_role_name
89
-
90
- policy = jsonencode({
91
- Version = "2012-10-17"
92
- Statement = [
93
- {
94
- Effect = "Allow"
95
- Action = [
96
- "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
97
- "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
98
- "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
99
- ]
100
- Resource = [
101
- module.my_table.table_arn,
102
- "${module.my_table.table_arn}/index/*",
103
- ]
104
- },
105
- {
106
- Effect = "Allow"
107
- Action = [
108
- "kms:Encrypt",
109
- "kms:Decrypt",
110
- "kms:ReEncrypt*",
111
- "kms:GenerateDataKey*",
112
- "kms:DescribeKey",
113
- ]
114
- Resource = [module.my_table.kms_key_arn]
115
- },
116
- ]
117
- })
89
+ module "my_mcp_server" {
90
+ source = "../../common/terraform/src/app/mcp-servers/my-mcp-server"
91
+
92
+ additional_iam_policy_statements = [
93
+ {
94
+ Effect = "Allow"
95
+ Action = [
96
+ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem",
97
+ "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan",
98
+ "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem",
99
+ ]
100
+ Resource = [
101
+ module.my_table.table_arn,
102
+ "${module.my_table.table_arn}/index/*",
103
+ ]
104
+ },
105
+ {
106
+ Effect = "Allow"
107
+ Action = [
108
+ "kms:Encrypt",
109
+ "kms:Decrypt",
110
+ "kms:ReEncrypt*",
111
+ "kms:GenerateDataKey*",
112
+ "kms:DescribeKey",
113
+ ]
114
+ Resource = [module.my_table.kms_key_arn]
115
+ },
116
+ ]
118
117
  }
119
118
  ```
120
119
  </Fragment>
@@ -160,16 +160,7 @@ resource "aws_vpc_security_group_egress_rule" "mcp_server_to_database" {
160
160
  }
161
161
  ```
162
162
 
163
- `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
164
-
165
- ```hcl title="packages/infra/src/main.tf"
166
- module "runtime_config_appconfig" {
167
- source = "../../common/terraform/src/core/runtime-config/appconfig"
168
-
169
- application_name = "my-app-runtime-config"
170
- namespaces = ["connection", "agentcore", "database"]
171
- }
172
- ```
163
+ `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
173
164
 
174
165
  </Fragment>
175
166
  </Infrastructure>
@@ -602,7 +602,7 @@ If you change the prefix for your stage names in your infrastructure project's `
602
602
  Additionally it's worth noting that the `load-runtime-config` target assumes a single stage of your application is deployed to the environment you have AWS credentials for. You will need to adjust the command if you deploy multiple stages to the same account and region.
603
603
  </Fragment>
604
604
  <Fragment slot="terraform">
605
- For Terraform projects, the `load-runtime-config` target copies the `runtime-config.json` file that was created after your most recent local `terraform apply`.
605
+ For Terraform projects, the `load-runtime-config` target copies the runtime config your most recent local `terraform apply` aggregated, from `dist/packages/common/terraform/runtime-config/connection.json`.
606
606
  </Fragment>
607
607
  </Infrastructure>
608
608
  :::
@@ -12,17 +12,19 @@ Runtime configuration is the mechanism used by Nx Plugin for AWS to pass deploy-
12
12
 
13
13
  Runtime configuration is organised into **namespaces**. Each namespace is a logical grouping of related configuration values. At deploy time, all namespaces are stored in **AWS AppConfig** as Configuration Profiles.
14
14
 
15
- Two built-in namespaces are used by generated constructs:
15
+ Four built-in namespaces are used by generated constructs:
16
16
 
17
17
  - **`connection`** — configuration that enables generated projects to connect to each other:
18
18
  - **API URLs** — registered automatically by API constructs
19
19
  - **Cognito settings** — registered automatically by the UserIdentity construct
20
20
  - **Agent runtime ARNs** — added by the connection generator when you connect a React website to an Agent
21
21
  - **`agentcore`** — AgentCore runtime ARNs for agents and MCP servers. Registered automatically by the agent/MCP constructs and used for server-side discovery (agent → agent via A2A, agent → MCP server).
22
+ - **`dynamodb`** — table names, registered automatically by DynamoDB table constructs and read by the generated table client.
23
+ - **`database`** — Aurora connection details, registered automatically by relational database constructs and read by the generated database client.
22
24
 
23
- The `connection` namespace is also deployed as a `runtime-config.json` file to your website's S3 bucket, enabling client-side discovery of backend resources. The `agentcore` namespace is server-side only (via AppConfig) so agent runtime ARNs are not exposed to the frontend unless you explicitly connect a website to an agent.
25
+ The `connection` namespace is also deployed as a `runtime-config.json` file to your website's S3 bucket, enabling client-side discovery of backend resources. The other namespaces are server-side only (via AppConfig), so values such as agent runtime ARNs and table names are not exposed to the frontend unless you explicitly connect a website to them.
24
26
 
25
- You can define as many additional namespaces as you like, providing a convenient alternative to environment variables for passing deploy-time values such as DynamoDB table names to your Lambda functions or other compute resources.
27
+ You can define as many additional namespaces as you like, providing a convenient alternative to environment variables for passing deploy-time values to your Lambda functions or other compute resources.
26
28
 
27
29
  ```d2
28
30
  direction: down
@@ -107,6 +109,17 @@ Terraform wires runtime configuration across three `core/runtime-config/*` modul
107
109
  }
108
110
  ```
109
111
 
112
+ The `namespaces` variable defaults to every built-in namespace, so generated modules work without configuring it. To add namespaces of your own, list them alongside the built-in ones:
113
+
114
+ ```hcl title="packages/infra/src/main.tf"
115
+ module "runtime_config_appconfig" {
116
+ source = "../../common/terraform/src/core/runtime-config/appconfig"
117
+
118
+ application_name = "my-app-runtime-config"
119
+ namespaces = ["connection", "agentcore", "database", "dynamodb", "tables"]
120
+ }
121
+ ```
122
+
110
123
  2. **`core/runtime-config/entry`** — one invocation per contribution. Generated API, agent and MCP modules call this internally to publish their URLs and ARNs. Call it directly to publish custom configuration.
111
124
 
112
125
  ```hcl title="packages/infra/src/main.tf"
@@ -38,7 +38,7 @@ module "my_table" {
38
38
  }
39
39
 
40
40
  resource "aws_iam_role_policy" "dynamodb_access" {
41
- role = module.my_api.lambda_role_name
41
+ role = module.my_api.lambda_execution_role_name
42
42
 
43
43
  policy = jsonencode({
44
44
  Version = "2012-10-17"
@@ -89,16 +89,7 @@ resource "aws_vpc_security_group_egress_rule" "api_to_database" {
89
89
  }
90
90
  ```
91
91
 
92
- Deploy the API Lambda functions into **private subnets with egress**, not private isolated subnets. `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module — passing them sets `RUNTIME_CONFIG_APP_ID` on the Lambda functions and grants them read access to the application. Include the `database` namespace when instantiating it so the database module's runtime configuration entry is deployed:
93
-
94
- ```hcl title="packages/infra/src/main.tf"
95
- module "runtime_config_appconfig" {
96
- source = "../../common/terraform/src/core/runtime-config/appconfig"
97
-
98
- application_name = "my-app-runtime-config"
99
- namespaces = ["connection", "agentcore", "database"]
100
- }
101
- ```
92
+ Deploy the API Lambda functions into **private subnets with egress**, not private isolated subnets. `appconfig_application_id`/`appconfig_application_arn` come from the shared <Link path="guides/runtime-config">runtime configuration</Link> AppConfig application declared once in your root module, not from the database module — passing them sets `RUNTIME_CONFIG_APP_ID` on the Lambda functions and grants them read access to the application. That application exposes the `database` namespace by default, so the database module's runtime configuration entry is deployed without further configuration.
102
93
 
103
94
  </Fragment>
104
95
  </Infrastructure>
@@ -46,27 +46,42 @@ This provisions a DynamoDB table with:
46
46
  - On-demand (`PAY_PER_REQUEST`) billing
47
47
  - Customer-managed KMS encryption with automatic key rotation
48
48
  - Point-in-time recovery enabled
49
- - Deletion protection enabled
50
- - Table name registered in Runtime Config
49
+ - Deletion protection enabled, plus a `prevent_destroy` lifecycle guard
50
+ - Table name registered in Runtime Config under the `dynamodb` namespace in AWS AppConfig
51
+
52
+ The `core/runtime-config/appconfig` module exposes the `dynamodb` namespace by default, so the table name is deployed without further configuration. If you pass `namespaces` to that module explicitly, keep `dynamodb` in the list — otherwise no configuration profile is created for it and the generated table client cannot resolve the table name.
51
53
  </Fragment>
52
54
  </Infrastructure>
53
55
 
54
56
  ### Deletion Protection
55
57
 
56
- Deletion protection is enabled by default to prevent accidental table deletion.
58
+ The table is protected by two independent guards, so that turning off either one alone cannot delete your data:
57
59
 
58
- #### Disable Deletion Protection
60
+ <Infrastructure>
61
+ <Fragment slot="cdk">
62
+ - `deletionProtection`, enforced by DynamoDB.
63
+ - `RemovalPolicy.RETAIN`, enforced by CloudFormation, which leaves the table in place when it is removed from the stack.
64
+ </Fragment>
65
+ <Fragment slot="terraform">
66
+ - `deletion_protection_enabled`, enforced by DynamoDB.
67
+ - `lifecycle { prevent_destroy = true }` on the table in `common/terraform/src/core/dynamodb/dynamodb.tf`, enforced by Terraform, which fails any plan that would destroy the table.
68
+ </Fragment>
69
+ </Infrastructure>
59
70
 
60
- Disable it for environments where table deletion is expected, such as short-lived development or preview stacks.
71
+ #### Deleting the Table
72
+
73
+ Disable protection for environments where table deletion is expected, such as short-lived development or preview stacks.
61
74
 
62
75
  <Infrastructure>
63
76
  <Fragment slot="cdk">
64
77
 
65
78
  ```ts title="packages/infra/src/stacks/application-stack.ts"
79
+ import { RemovalPolicy } from 'aws-cdk-lib';
66
80
  import { MyTable } from '@my-scope/common-constructs';
67
81
 
68
82
  const table = new MyTable(this, 'Table', {
69
83
  deletionProtection: false,
84
+ removalPolicy: RemovalPolicy.DESTROY,
70
85
  });
71
86
  ```
72
87
  </Fragment>
@@ -78,6 +93,22 @@ module "my_table" {
78
93
  deletion_protection_enabled = false
79
94
  }
80
95
  ```
96
+
97
+ `prevent_destroy` must be a literal — Terraform does not allow it to reference a variable — so it cannot be turned off from `main.tf`. Also remove the `lifecycle` block from the table in `common/terraform/src/core/dynamodb/dynamodb.tf`:
98
+
99
+ ```hcl title="packages/common/terraform/src/core/dynamodb/dynamodb.tf" del={4-6}
100
+ resource "aws_dynamodb_table" "table" {
101
+ # ...
102
+
103
+ lifecycle {
104
+ prevent_destroy = true
105
+ }
106
+ }
107
+ ```
108
+
109
+ :::caution
110
+ This module is shared by every table in your workspace, so removing the block removes that guard for all of them.
111
+ :::
81
112
  </Fragment>
82
113
  </Infrastructure>
83
114
 
@@ -3,21 +3,34 @@ title: Deletion Protection
3
3
  ---
4
4
  import Infrastructure from '@components/infrastructure.astro';
5
5
 
6
- Deletion protection is enabled by default (`deletionProtection: true` in CDK, `deletion_protection = true` in Terraform) to protect the Aurora cluster from accidental deletion.
6
+ The Aurora cluster is protected by two independent guards, so that turning off either one alone cannot delete your data:
7
7
 
8
- #### Disable Deletion Protection
8
+ <Infrastructure>
9
+ <Fragment slot="cdk">
10
+ - `deletionProtection`, enforced by RDS.
11
+ - `RemovalPolicy.RETAIN`, enforced by CloudFormation, which leaves the cluster in place when it is removed from the stack.
12
+ </Fragment>
13
+ <Fragment slot="terraform">
14
+ - `deletion_protection`, enforced by RDS.
15
+ - `lifecycle { prevent_destroy = true }` on the cluster in `common/terraform/src/core/rdb/aurora/aurora.tf`, enforced by Terraform, which fails any plan that would destroy the cluster.
16
+ </Fragment>
17
+ </Infrastructure>
18
+
19
+ #### Deleting the Database
9
20
 
10
- You can disable deletion protection for environments where database deletion is expected, such as short-lived development or preview stacks.
21
+ You can disable protection for environments where database deletion is expected, such as short-lived development or preview stacks.
11
22
 
12
23
  <Infrastructure>
13
24
  <Fragment slot="cdk">
14
25
 
15
26
  ```ts title="packages/infra/src/stacks/application-stack.ts"
27
+ import { RemovalPolicy } from 'aws-cdk-lib';
16
28
  import { MyDatabase } from '@my-scope/common-constructs';
17
29
 
18
30
  const db = new MyDatabase(this, 'Db', {
19
31
  ...
20
32
  deletionProtection: false,
33
+ removalPolicy: RemovalPolicy.DESTROY,
21
34
  });
22
35
  ```
23
36
  </Fragment>
@@ -28,7 +41,24 @@ module "my_database" {
28
41
  source = "../../common/terraform/src/app/dbs/my-database"
29
42
  ...
30
43
  deletion_protection = false
44
+ skip_final_snapshot = true
31
45
  }
32
46
  ```
47
+
48
+ `prevent_destroy` must be a literal — Terraform does not allow it to reference a variable — so it cannot be turned off from `main.tf`. Also remove the `lifecycle` block from the cluster in `common/terraform/src/core/rdb/aurora/aurora.tf`:
49
+
50
+ ```hcl title="packages/common/terraform/src/core/rdb/aurora/aurora.tf" del={4-6}
51
+ resource "aws_rds_cluster" "database" {
52
+ # ...
53
+
54
+ lifecycle {
55
+ prevent_destroy = true
56
+ }
57
+ }
58
+ ```
59
+
60
+ :::caution
61
+ This module is shared by every database in your workspace, so removing the block removes that guard for all of them.
62
+ :::
33
63
  </Fragment>
34
64
  </Infrastructure>
@@ -52,16 +52,7 @@ module "my_database" {
52
52
 
53
53
  This provisions an Aurora cluster with RDS Proxy, admin credentials, create-db-user Lambda, runtime config registration, migration Lambda, and container registry resources.
54
54
 
55
- The database module registers its connection details under the `database` runtime configuration namespace. Include this namespace when instantiating the shared runtime configuration AppConfig application:
56
-
57
- ```hcl title="packages/infra/src/main.tf"
58
- module "runtime_config_appconfig" {
59
- source = "../../common/terraform/src/core/runtime-config/appconfig"
60
-
61
- application_name = "my-app-runtime-config"
62
- namespaces = ["connection", "agentcore", "database"]
63
- }
64
- ```
55
+ The database module registers its connection details under the `database` <Link path="guides/runtime-config">runtime configuration</Link> namespace, which the shared runtime configuration AppConfig application exposes by default.
65
56
 
66
57
  The generated infrastructure creates two database users:
67
58
  - **Admin user** - Created during cluster provisioning with credentials stored in AWS Secrets Manager
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin-mcp",
3
- "version": "1.0.0-rc.81",
3
+ "version": "1.0.0-rc.83",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",