@intentius/chant-lexicon-aws 0.44.13 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agentcore/trace-fetch.d.ts +4 -1
- package/dist/agentcore/trace-fetch.d.ts.map +1 -1
- package/dist/api/read-client.d.ts +31 -1
- package/dist/api/read-client.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/cloud-executor.d.ts +9 -0
- package/dist/components/cloud-executor.d.ts.map +1 -1
- package/dist/composites/agentcore-agent.d.ts +33 -19
- package/dist/composites/agentcore-agent.d.ts.map +1 -1
- package/dist/composites/index.d.ts +1 -1
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/deep-observe.d.ts +21 -0
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/op/activities/aws-apply.d.ts +14 -4
- package/dist/op/activities/aws-apply.d.ts.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/properties.d.ts +4 -3
- package/dist/properties.d.ts.map +1 -1
- package/dist/spec/fetch.d.ts +12 -1
- package/dist/spec/fetch.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/agentcore/trace-fetch.test.ts +17 -0
- package/src/agentcore/trace-fetch.ts +7 -2
- package/src/api/read-client.test.ts +87 -0
- package/src/api/read-client.ts +57 -1
- package/src/codegen/docs-links.test.ts +44 -30
- package/src/codegen/docs.ts +2 -1034
- package/src/components/capability-plugin.ts +5 -2
- package/src/components/cloud-executor.test.ts +29 -1
- package/src/components/cloud-executor.ts +23 -5
- package/src/composites/agentcore-agent.test.ts +32 -12
- package/src/composites/agentcore-agent.ts +43 -23
- package/src/composites/index.ts +1 -1
- package/src/composites/microvm-app.test.ts +2 -2
- package/src/deep-observe.test.ts +94 -0
- package/src/deep-observe.ts +58 -2
- package/src/import/roundtrip-fixtures.test.ts +1 -1
- package/src/index.ts +3 -1
- package/src/lifecycle-integration.test.ts +89 -0
- package/src/op/activities/aws-apply.test.ts +40 -4
- package/src/op/activities/aws-apply.ts +23 -7
- package/src/plugin.ts +34 -35
- package/src/properties.test.ts +5 -5
- package/src/properties.ts +6 -5
- package/src/serializer.test.ts +73 -33
- package/src/spec/fetch.test.ts +40 -0
- package/src/spec/fetch.ts +24 -3
package/src/codegen/docs.ts
CHANGED
|
@@ -108,9 +108,9 @@ export async function generateDocs(options?: { verbose?: boolean }): Promise<voi
|
|
|
108
108
|
// mechanism azure/helm already use), so its "Folds?" column can never
|
|
109
109
|
// drift from the registration the way #1062's foldability matrix
|
|
110
110
|
// depends on. The hand-written usage guide with full worked examples
|
|
111
|
-
// moves to a separate "intrinsics-guide" page
|
|
111
|
+
// moves to a separate "intrinsics-guide" page in docs/pages/ — content
|
|
112
112
|
// unchanged, just no longer sharing a slug with generated data.
|
|
113
|
-
// `rules` is NOT suppressed: the hand-written `lint-rules` page
|
|
113
|
+
// `rules` is NOT suppressed: the hand-written `lint-rules` page in docs/pages/
|
|
114
114
|
// explains 26 of the lexicon's 50 rules in depth, and the whole WAW032+
|
|
115
115
|
// hardening pass had no entry there at all (#1312). The generated table is
|
|
116
116
|
// the complete, always-current list, so both ship — the overview/reference
|
|
@@ -118,1038 +118,6 @@ export async function generateDocs(options?: { verbose?: boolean }): Promise<voi
|
|
|
118
118
|
// would just create a third copy to drift.
|
|
119
119
|
suppressPages: ["pseudo-parameters"],
|
|
120
120
|
examplesDir: join(pkgDir, "examples"),
|
|
121
|
-
extraPages: [
|
|
122
|
-
{
|
|
123
|
-
slug: "cloudformation",
|
|
124
|
-
title: "CloudFormation Concepts",
|
|
125
|
-
description: "Templates, resources, parameters, outputs, dependencies, and tagging in the AWS CloudFormation lexicon",
|
|
126
|
-
content: `Every exported resource declaration becomes a logical resource in a CloudFormation template. The serializer handles the translation automatically:
|
|
127
|
-
|
|
128
|
-
- Wraps output in \`AWSTemplateFormatVersion: "2010-09-09"\`
|
|
129
|
-
- Converts camelCase property names to PascalCase (CloudFormation convention)
|
|
130
|
-
- Resolves \`AttrRef\` references to \`Fn::GetAtt\`
|
|
131
|
-
- Resolves resource references to \`Ref\` intrinsics
|
|
132
|
-
|
|
133
|
-
{{file:lambda-s3/src/main.ts}}
|
|
134
|
-
|
|
135
|
-
The \`LambdaS3\` composite expands to 3 CloudFormation resources: an S3 Bucket, an IAM Role (with S3 read policy), and a Lambda Function. Property names like \`BucketName\` use the CloudFormation spec-native PascalCase directly, and the export name \`app\` becomes the resource name prefix (e.g. \`appBucket\`, \`appRole\`, \`appFunc\`).
|
|
136
|
-
|
|
137
|
-
## Resource types and naming
|
|
138
|
-
|
|
139
|
-
CloudFormation resource types like \`AWS::S3::Bucket\` are mapped to short TypeScript class names. The lexicon uses a naming strategy that prioritizes readability:
|
|
140
|
-
|
|
141
|
-
| CloudFormation Type | Chant Class | Rule |
|
|
142
|
-
|---|---|---|
|
|
143
|
-
| \`AWS::S3::Bucket\` | \`Bucket\` | Priority name (common resource) |
|
|
144
|
-
| \`AWS::Lambda::Function\` | \`Function\` | Priority name |
|
|
145
|
-
| \`AWS::IAM::Role\` | \`Role\` | Priority name |
|
|
146
|
-
| \`AWS::EC2::Instance\` | \`Instance\` | Short name (last segment) |
|
|
147
|
-
| \`AWS::EC2::SecurityGroup\` | \`SecurityGroup\` | Short name |
|
|
148
|
-
| \`AWS::ECS::Service\` | \`EcsService\` | Service-prefixed (avoids collision with \`AWS::AppRunner::Service\`) |
|
|
149
|
-
|
|
150
|
-
Common resources get fixed short names for stability. When two services define the same resource name (e.g. both ECS and AppRunner have \`Service\`), the less common one gets a service prefix.
|
|
151
|
-
|
|
152
|
-
**Discovering available resources:** Your editor's autocomplete is the best tool — every resource is a named export from the lexicon. You can also run \`chant list\` to see all resource types, or browse the generated TypeScript types.
|
|
153
|
-
|
|
154
|
-
## Imports and cross-file references
|
|
155
|
-
|
|
156
|
-
Chant projects use standard TypeScript imports. Lexicon types come from the lexicon package, and cross-file references are standard imports:
|
|
157
|
-
|
|
158
|
-
{{file:lambda-api/src/health-api.ts}}
|
|
159
|
-
|
|
160
|
-
When you reference a resource or attribute from another file (e.g. \`dataBucket.Arn\`), the serializer resolves it to \`Fn::GetAtt\` or \`Ref\` as appropriate. This is how cross-file references work — standard imports, no indirection.
|
|
161
|
-
|
|
162
|
-
## Parameters
|
|
163
|
-
|
|
164
|
-
CloudFormation parameters let you customize a stack at deploy time. Export a \`Parameter\` to add it to the template's \`Parameters\` section:
|
|
165
|
-
|
|
166
|
-
{{file:docs-snippets/src/parameter-declaration.ts}}
|
|
167
|
-
|
|
168
|
-
Produces:
|
|
169
|
-
|
|
170
|
-
\`\`\`json
|
|
171
|
-
"Parameters": {
|
|
172
|
-
"Environment": {
|
|
173
|
-
"Type": "String",
|
|
174
|
-
"Default": "dev",
|
|
175
|
-
"Description": "Deployment environment"
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
\`\`\`
|
|
179
|
-
|
|
180
|
-
Reference parameters with \`Ref\`:
|
|
181
|
-
|
|
182
|
-
{{file:docs-snippets/src/parameter-cross-file-ref.ts}}
|
|
183
|
-
|
|
184
|
-
## Outputs
|
|
185
|
-
|
|
186
|
-
Use \`output()\` to create explicit stack outputs. Accepts an \`AttrRef\` (resource attribute)
|
|
187
|
-
or any intrinsic (e.g. \`Sub\`, \`Join\`) for computed values. Cross-resource \`AttrRef\` usage
|
|
188
|
-
is also auto-detected and promoted to outputs when needed.
|
|
189
|
-
|
|
190
|
-
{{file:docs-snippets/src/output-explicit.ts}}
|
|
191
|
-
|
|
192
|
-
Produces:
|
|
193
|
-
|
|
194
|
-
\`\`\`json
|
|
195
|
-
"Outputs": {
|
|
196
|
-
"DataBucketArn": {
|
|
197
|
-
"Value": { "Fn::GetAtt": ["DataBucket", "Arn"] }
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
\`\`\`
|
|
201
|
-
|
|
202
|
-
Use \`Sub\` to export a computed value like a constructed URL:
|
|
203
|
-
|
|
204
|
-
\`\`\`typescript
|
|
205
|
-
export const solrUrl = output(Sub\`http://\${Ref(albDnsName)}/solr\`, "solrUrl");
|
|
206
|
-
\`\`\`
|
|
207
|
-
|
|
208
|
-
## Pseudo-parameters
|
|
209
|
-
|
|
210
|
-
Runtime context values available in every template, accessed via the \`AWS\` namespace:
|
|
211
|
-
|
|
212
|
-
{{file:docs-snippets/src/pseudo-params.ts}}
|
|
213
|
-
|
|
214
|
-
| Pseudo-parameter | Description |
|
|
215
|
-
|---|---|
|
|
216
|
-
| \`AWS.StackName\` | Name of the stack |
|
|
217
|
-
| \`AWS.Region\` | AWS region |
|
|
218
|
-
| \`AWS.AccountId\` | AWS account ID |
|
|
219
|
-
| \`AWS.StackId\` | Stack ID |
|
|
220
|
-
| \`AWS.URLSuffix\` | Domain suffix (usually \`amazonaws.com\`) |
|
|
221
|
-
| \`AWS.Partition\` | Partition (\`aws\`, \`aws-cn\`, \`aws-us-gov\`) |
|
|
222
|
-
| \`AWS.NotificationARNs\` | Notification ARNs |
|
|
223
|
-
| \`AWS.NoValue\` | Removes property when used with \`Fn::If\` |
|
|
224
|
-
|
|
225
|
-
## Intrinsic functions
|
|
226
|
-
|
|
227
|
-
The lexicon provides 9 intrinsic functions (\`Sub\`, \`Ref\`, \`GetAtt\`, \`If\`, \`Join\`, \`Select\`, \`Split\`, \`Base64\`, \`GetAZs\`) that map directly to CloudFormation \`Fn::\` calls. See [Intrinsic Functions](../intrinsics/) for the reference table or the [Intrinsics Guide](../intrinsics-guide/) for full usage examples.
|
|
228
|
-
|
|
229
|
-
## Dependencies
|
|
230
|
-
|
|
231
|
-
CloudFormation automatically creates dependencies between resources when you use \`Ref\` or \`Fn::GetAtt\`. Chant leverages this — when you reference \`$.myBucket.arn\`, the serializer emits \`Fn::GetAtt\` and CloudFormation infers the dependency.
|
|
232
|
-
|
|
233
|
-
For cases where you need an explicit dependency without a property reference, pass \`DependsOn\` as a resource-level attribute (second constructor argument):
|
|
234
|
-
|
|
235
|
-
{{file:docs-snippets/src/depends-on.ts}}
|
|
236
|
-
|
|
237
|
-
\`DependsOn\` values can be string logical names or references to other resource objects — Declarable references are resolved to their logical names automatically at build time.
|
|
238
|
-
|
|
239
|
-
The \`WAW010\` post-synth check warns if a \`DependsOn\` target is already referenced via \`Ref\` or \`Fn::GetAtt\` in properties — in that case the explicit dependency is redundant.
|
|
240
|
-
|
|
241
|
-
## Resource attributes
|
|
242
|
-
|
|
243
|
-
Every resource constructor accepts an optional second argument for CloudFormation resource-level attributes. These control lifecycle behavior, conditional creation, and metadata — they are distinct from resource *properties* (the first argument).
|
|
244
|
-
|
|
245
|
-
{{file:docs-snippets/src/resource-attributes.ts}}
|
|
246
|
-
|
|
247
|
-
| Attribute | Type | Description |
|
|
248
|
-
|-----------|------|-------------|
|
|
249
|
-
| \`DependsOn\` | \`Declarable \\| Declarable[] \\| string \\| string[]\` | Explicit ordering dependency. Accepts resource references or logical name strings. |
|
|
250
|
-
| \`Condition\` | \`string\` | Only create this resource when the named Condition evaluates to true. |
|
|
251
|
-
| \`DeletionPolicy\` | \`"Delete" \\| "Retain" \\| "RetainExceptOnCreate" \\| "Snapshot"\` | What happens when the resource is removed from the template or the stack is deleted. |
|
|
252
|
-
| \`UpdateReplacePolicy\` | \`"Delete" \\| "Retain" \\| "Snapshot"\` | What happens to the old resource when CloudFormation replaces it during an update. |
|
|
253
|
-
| \`UpdatePolicy\` | \`object\` | Controls how Auto Scaling Groups perform rolling updates (\`AutoScalingRollingUpdate\`, \`AutoScalingReplacingUpdate\`). |
|
|
254
|
-
| \`CreationPolicy\` | \`object\` | Wait for resource signals before marking creation complete (\`ResourceSignal\` with \`Count\` and \`Timeout\`). |
|
|
255
|
-
| \`Metadata\` | \`Record<string, unknown>\` | Arbitrary metadata. Commonly used for \`AWS::CloudFormation::Init\` (cfn-init bootstrapping). Intrinsic functions in metadata values are resolved at build time. |
|
|
256
|
-
|
|
257
|
-
All attributes are optional. When omitted, CloudFormation uses its defaults (e.g. \`DeletionPolicy: "Delete"\`).
|
|
258
|
-
|
|
259
|
-
## Policy documents
|
|
260
|
-
|
|
261
|
-
IAM policy documents appear on many AWS resources — \`Role.assumeRolePolicyDocument\`, \`ManagedPolicy.policyDocument\`, \`BucketPolicy.policyDocument\`, and others. These properties are typed as \`PolicyDocument\`, giving you autocomplete for the IAM JSON Policy Language.
|
|
262
|
-
|
|
263
|
-
The \`PolicyDocument\` interface and its supporting types:
|
|
264
|
-
|
|
265
|
-
| Type | Fields |
|
|
266
|
-
|------|--------|
|
|
267
|
-
| \`PolicyDocument\` | \`Version?\` (\`"2012-10-17"\` \\| \`"2008-10-17"\`), \`Id?\`, \`Statement\` |
|
|
268
|
-
| \`IamPolicyStatement\` | \`Effect\` (\`"Allow"\` \\| \`"Deny"\`), \`Action?\`, \`Resource?\`, \`Principal?\`, \`Condition?\`, and their \`Not\` variants |
|
|
269
|
-
| \`IamPolicyPrincipal\` | \`"*"\` or \`{ AWS?, Service?, Federated? }\` |
|
|
270
|
-
|
|
271
|
-
Policy documents use **PascalCase keys** (\`Effect\`, \`Action\`, \`Resource\`) because they follow the IAM JSON Policy Language spec — CloudFormation passes them through to IAM as-is, unlike resource properties which are automatically converted from camelCase.
|
|
272
|
-
|
|
273
|
-
The recommended pattern is to extract policies into your \`defaults.ts\` and import them directly:
|
|
274
|
-
|
|
275
|
-
{{file:docs-snippets/src/policy-trust.ts}}
|
|
276
|
-
|
|
277
|
-
Then reference them from resource files:
|
|
278
|
-
|
|
279
|
-
{{file:docs-snippets/src/policy-role.ts}}
|
|
280
|
-
|
|
281
|
-
For scoped resource ARNs, use \`Sub\` in the policy constant:
|
|
282
|
-
|
|
283
|
-
{{file:docs-snippets/src/policy-scoped.ts}}
|
|
284
|
-
|
|
285
|
-
The \`IamPolicyPrincipal\` type supports all principal forms — wildcard (\`"*"\`), AWS accounts, services, and federated providers:
|
|
286
|
-
|
|
287
|
-
\`\`\`typescript
|
|
288
|
-
// Wildcard principal
|
|
289
|
-
Principal: "*",
|
|
290
|
-
|
|
291
|
-
// Service principal
|
|
292
|
-
Principal: { Service: "lambda.amazonaws.com" },
|
|
293
|
-
|
|
294
|
-
// Cross-account
|
|
295
|
-
Principal: { AWS: "arn:aws:iam::123456789012:root" },
|
|
296
|
-
|
|
297
|
-
// Multiple services
|
|
298
|
-
Principal: { Service: ["lambda.amazonaws.com", "edgelambda.amazonaws.com"] },
|
|
299
|
-
\`\`\`
|
|
300
|
-
|
|
301
|
-
## Conditions
|
|
302
|
-
|
|
303
|
-
Use the \`If\` intrinsic for conditional values within resource properties:
|
|
304
|
-
|
|
305
|
-
{{file:docs-snippets/src/conditions.ts}}
|
|
306
|
-
|
|
307
|
-
CloudFormation \`Conditions\` blocks are recognized by the serializer when importing existing templates. For new stacks, use TypeScript logic for build-time decisions and \`If\` for deploy-time decisions.
|
|
308
|
-
|
|
309
|
-
## Mappings
|
|
310
|
-
|
|
311
|
-
CloudFormation Mappings are a static lookup mechanism. In chant, use TypeScript objects instead — they're evaluated at build time and produce the same result:
|
|
312
|
-
|
|
313
|
-
{{file:docs-snippets/src/mappings.ts}}
|
|
314
|
-
|
|
315
|
-
For deploy-time region lookups, combine \`AWS.Region\` with \`If\` or use \`Fn::Sub\` with SSM parameter store references.
|
|
316
|
-
|
|
317
|
-
## Nested stacks
|
|
318
|
-
|
|
319
|
-
:::caution
|
|
320
|
-
Nested stacks add deployment complexity and are not recommended for most projects. Prefer [flat composites](../composites/) instead.
|
|
321
|
-
:::
|
|
322
|
-
|
|
323
|
-
CloudFormation nested stacks (\`AWS::CloudFormation::Stack\`) split resources into child templates. The lexicon supports them via \`nestedStack()\` for cases where you exceed the 500-resource limit or need to package reusable infrastructure as a black box. See the [Nested Stacks](../nested-stacks/) page for details.
|
|
324
|
-
|
|
325
|
-
## Tagging
|
|
326
|
-
|
|
327
|
-
Use \`defaultTags()\` to declare project-wide tags. The serializer automatically injects them into every taggable resource at synthesis time:
|
|
328
|
-
|
|
329
|
-
{{file:docs-snippets/src/tagging.ts}}
|
|
330
|
-
|
|
331
|
-
No other changes needed — all taggable resources in the project get these tags automatically. Resources with explicit \`Tags\` keep them (explicit key wins over default). Non-taggable resources like \`AWS::Lambda::Permission\` are never tagged.
|
|
332
|
-
|
|
333
|
-
Tag values support strings, \`Parameter\` references, and intrinsic functions (\`Sub\`, \`Ref\`, etc.).`,
|
|
334
|
-
},
|
|
335
|
-
{
|
|
336
|
-
slug: "intrinsics-guide",
|
|
337
|
-
title: "Intrinsics Guide",
|
|
338
|
-
description: "Worked examples for every CloudFormation intrinsic function and their chant syntax",
|
|
339
|
-
content: `See [Intrinsic Functions](../intrinsics/) for the generated reference table (name, description, output key, whether it's a tagged template, whether folding can reduce it). This page is the worked-example companion — one \`Fn::\` intrinsic function per section, with real usage.
|
|
340
|
-
|
|
341
|
-
CloudFormation intrinsic functions are available as imports from the lexicon. They produce the corresponding \`Fn::\` calls in the serialized template.
|
|
342
|
-
|
|
343
|
-
Only \`Sub\` is a tagged template — the others below are plain function calls. Both forms fold on the [default build path](/chant/concepts/typescript-as-data/#folded-vs-run) ([#1044](https://github.com/INTENTIUS/chant/issues/1044)): every AWS intrinsic on this page is registered with its call form opted in, so using \`Ref\`, \`GetAtt\`, \`If\`, \`Join\`, \`Select\`, \`Split\`, \`Base64\`, or \`GetAZs\` in a resource's props no longer forces that file back to the run path. What folds is the call, not calls in general — the name has to be one this lexicon registered and opted in, imported from this lexicon by the file using it. A same-file resource passed to one (\`Ref(bucket)\` where \`bucket\` is declared in the same file) still falls back, since the intrinsic needs the real constructed resource.
|
|
344
|
-
|
|
345
|
-
Here is a complete example using all intrinsic functions:
|
|
346
|
-
|
|
347
|
-
{{file:docs-snippets/src/intrinsics.ts}}
|
|
348
|
-
|
|
349
|
-
## \`Sub\` — string substitution
|
|
350
|
-
|
|
351
|
-
Tagged template literal that produces \`Fn::Sub\`. The most common intrinsic — use it for dynamic naming with pseudo-parameters and attribute references:
|
|
352
|
-
|
|
353
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:3-5}}
|
|
354
|
-
|
|
355
|
-
\`Sub\` is a tagged template — use it with backticks, not as a function call.
|
|
356
|
-
|
|
357
|
-
## \`Ref\` — resource and parameter references
|
|
358
|
-
|
|
359
|
-
References a resource's physical ID or a parameter's value:
|
|
360
|
-
|
|
361
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:7-9}}
|
|
362
|
-
|
|
363
|
-
In most cases you don't need \`Ref\` directly — the serializer automatically generates \`Ref\` when you reference an imported resource (e.g. \`dataBucket\` imported from another file).
|
|
364
|
-
|
|
365
|
-
## \`GetAtt\` — resource attributes
|
|
366
|
-
|
|
367
|
-
**Preferred:** Use AttrRef directly via the resource's typed properties. When you write \`dataBucket.arn\` (imported from the file that defines it), the serializer automatically emits \`Fn::GetAtt\`. Explicit \`GetAtt\` is only needed for dynamic or imported resource names.
|
|
368
|
-
|
|
369
|
-
## \`If\` — conditional values
|
|
370
|
-
|
|
371
|
-
Returns one of two values based on a condition:
|
|
372
|
-
|
|
373
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:11-12}}
|
|
374
|
-
|
|
375
|
-
Use with \`AWS.NoValue\` to conditionally omit a property — see [Conditions](#conditions) on the CloudFormation Concepts page.
|
|
376
|
-
|
|
377
|
-
## \`Join\` — join values
|
|
378
|
-
|
|
379
|
-
Joins values with a delimiter:
|
|
380
|
-
|
|
381
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:14-15}}
|
|
382
|
-
|
|
383
|
-
## \`Select\` — select by index
|
|
384
|
-
|
|
385
|
-
Selects a value from a list by index:
|
|
386
|
-
|
|
387
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:17-18}}
|
|
388
|
-
|
|
389
|
-
## \`Split\` — split string
|
|
390
|
-
|
|
391
|
-
Splits a string by a delimiter:
|
|
392
|
-
|
|
393
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:20-21}}
|
|
394
|
-
|
|
395
|
-
## \`Base64\` — encode to Base64
|
|
396
|
-
|
|
397
|
-
Encodes a string to Base64, commonly used for EC2 user data:
|
|
398
|
-
|
|
399
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:23-27}}
|
|
400
|
-
|
|
401
|
-
## \`GetAZs\` — availability zones
|
|
402
|
-
|
|
403
|
-
Returns the list of Availability Zones for a region:
|
|
404
|
-
|
|
405
|
-
{{file:docs-snippets/src/intrinsics-detail.ts:29-31}}`,
|
|
406
|
-
},
|
|
407
|
-
{
|
|
408
|
-
slug: "composites",
|
|
409
|
-
title: "Composites",
|
|
410
|
-
description: "Composite resources, built-in composites, action constants, and withDefaults presets in the AWS CloudFormation lexicon",
|
|
411
|
-
content: `Composites group related resources into reusable factories. See also the core [Composite Resources](/chant/guide/composite-resources/) guide.
|
|
412
|
-
|
|
413
|
-
{{file:lambda-api/src/lambda-api.ts}}
|
|
414
|
-
|
|
415
|
-
Instantiate and export:
|
|
416
|
-
|
|
417
|
-
{{file:lambda-api/src/health-api.ts}}
|
|
418
|
-
|
|
419
|
-
During build, composites expand to flat CloudFormation resources: \`healthApiRole\`, \`healthApiFunc\`, \`healthApiPermission\`.
|
|
420
|
-
|
|
421
|
-
A top-level composite call assigned directly to an export — like \`healthApi\` above — is one of the patterns [folding](/chant/concepts/typescript-as-data/#folded-vs-run) can reduce with no module execution (chant #1023). Defining a composite (the \`Composite(...)\` call inside \`lambda-api.ts\` itself) doesn't fold — its factory callback is a function, which is outside the fold subset — and neither does a composite call embedded as a nested value inside another resource's own properties; only a composite call that is itself a file's top-level export (or destructured/re-exported from one) is eligible.
|
|
422
|
-
|
|
423
|
-
## Built-in composites
|
|
424
|
-
|
|
425
|
-
The AWS lexicon ships ready-to-use composites for common patterns. Import them from \`@intentius/chant-lexicon-aws\`:
|
|
426
|
-
|
|
427
|
-
{{file:docs-snippets/src/builtin-composites.ts}}
|
|
428
|
-
|
|
429
|
-
| Composite | Members | Description |
|
|
430
|
-
|-----------|---------|-------------|
|
|
431
|
-
| \`LambdaFunction\` | \`role\`, \`func\` | IAM Role + Lambda Function. Auto-attaches \`AWSLambdaBasicExecutionRole\`; adds \`AWSLambdaVPCAccessExecutionRole\` when \`VpcConfig\` is provided. |
|
|
432
|
-
| \`LambdaNode\` | \`role\`, \`func\` | \`LambdaFunction\` preset with \`Runtime: "nodejs20.x"\` and \`Handler: "index.handler"\` |
|
|
433
|
-
| \`LambdaPython\` | \`role\`, \`func\` | \`LambdaFunction\` preset with \`Runtime: "python3.12"\` and \`Handler: "handler.handler"\` |
|
|
434
|
-
| \`LambdaApi\` | \`role\`, \`func\`, \`permission\` | \`LambdaFunction\` + Lambda Permission for API Gateway invocation |
|
|
435
|
-
| \`LambdaScheduled\` | \`role\`, \`func\`, \`rule\`, \`permission\` | \`LambdaFunction\` + EventBridge Rule + Lambda Permission |
|
|
436
|
-
| \`LambdaSqs\` | \`queue\`, \`role\`, \`func\` | SQS Queue + Lambda + EventSourceMapping. Auto-attaches SQS receive policy. |
|
|
437
|
-
| \`LambdaEventBridge\` | \`rule\`, \`role\`, \`func\`, \`permission\` | EventBridge Rule + Lambda. Supports \`schedule\` and/or \`eventPattern\`. |
|
|
438
|
-
| \`LambdaDynamoDB\` | \`table\`, \`role\`, \`func\` | DynamoDB Table + Lambda. Auto-attaches DynamoDB policy and injects \`TABLE_NAME\` env var. |
|
|
439
|
-
| \`LambdaS3\` | \`bucket\`, \`role\`, \`func\` | S3 Bucket (encrypted, public access blocked) + Lambda. Auto-attaches S3 policy and injects \`BUCKET_NAME\` env var. |
|
|
440
|
-
| \`LambdaSns\` | \`topic\`, \`role\`, \`func\`, \`subscription\`, \`permission\` | SNS Topic + Lambda via Subscription. Auto-attaches invoke permission for SNS. |
|
|
441
|
-
| \`VpcDefault\` | \`vpc\`, \`igw\`, \`igwAttachment\`, \`publicSubnet1\`, \`publicSubnet2\`, \`privateSubnet1\`, \`privateSubnet2\`, \`publicRouteTable\`, \`publicRoute\`, \`publicRta1\`, \`publicRta2\`, \`privateRouteTable\`, \`privateRta1\`, \`privateRta2\`, \`natEip\`, \`natGateway\`, \`privateRoute\` | Production-ready VPC: 2 public + 2 private subnets across 2 AZs, internet gateway, single NAT gateway. |
|
|
442
|
-
| \`FargateAlb\` | \`cluster\`, \`executionRole\`, \`taskRole\`, \`logGroup\`, \`taskDef\`, \`albSg\`, \`taskSg\`, \`alb\`, \`targetGroup\`, \`listener\`, \`service\` | Fargate service behind an ALB. Accepts VPC outputs as props. |
|
|
443
|
-
| \`AlbShared\` | \`cluster\`, \`executionRole\`, \`albSg\`, \`alb\`, \`listener\` | Shared ALB infrastructure (ECS cluster, execution role, ALB, listener with 404 default). Created once, consumed by multiple \`FargateService\` instances. |
|
|
444
|
-
| \`FargateService\` | \`taskRole\`, \`logGroup\`, \`taskDef\`, \`taskSg\`, \`targetGroup\`, \`rule\`, \`service\` | Per-service Fargate resources with listener rule routing. Wire to an \`AlbShared\` instance for multi-service ALB patterns. |
|
|
445
|
-
| \`RdsInstance\` | \`subnetGroup\`, \`sg\`, \`db\` (+ \`parameterGroup\` if configured) | RDS instance (postgres, mysql, mariadb) in private subnets. Creates DB subnet group, security group, and optionally a parameter group. Engine-specific defaults for port, username, and version. Encrypted by default. |
|
|
446
|
-
|
|
447
|
-
All built-in composites accept \`ManagedPolicyArns\` and \`Policies\` for adding IAM permissions to the auto-created role.
|
|
448
|
-
|
|
449
|
-
## Action constants
|
|
450
|
-
|
|
451
|
-
Typed IAM action constants for common AWS services. Use them in policy documents instead of hand-typing action strings:
|
|
452
|
-
|
|
453
|
-
{{file:docs-snippets/src/action-constants.ts}}
|
|
454
|
-
|
|
455
|
-
Available constants:
|
|
456
|
-
|
|
457
|
-
| Constant | Key groups |
|
|
458
|
-
|----------|------------|
|
|
459
|
-
| \`S3Actions\` | \`ReadOnly\`, \`WriteOnly\`, \`ReadWrite\`, \`Full\`, \`GetObject\`, \`PutObject\`, \`DeleteObject\`, \`ListObjects\` |
|
|
460
|
-
| \`LambdaActions\` | \`Invoke\`, \`ReadOnly\`, \`Full\` |
|
|
461
|
-
| \`DynamoDBActions\` | \`ReadOnly\`, \`WriteOnly\`, \`ReadWrite\`, \`Full\`, \`GetItem\`, \`PutItem\`, \`Query\`, \`Scan\` |
|
|
462
|
-
| \`SQSActions\` | \`SendMessage\`, \`ReceiveMessage\`, \`Full\` |
|
|
463
|
-
| \`SNSActions\` | \`Publish\`, \`Subscribe\`, \`Full\` |
|
|
464
|
-
| \`IAMActions\` | \`PassRole\` |
|
|
465
|
-
| \`ECRActions\` | \`Pull\`, \`Full\` |
|
|
466
|
-
| \`LogsActions\` | \`Write\`, \`Full\` |
|
|
467
|
-
| \`ECSActions\` | \`RunTask\`, \`Service\`, \`Full\` |
|
|
468
|
-
|
|
469
|
-
Broad groups like \`ReadWrite\` are always supersets of their narrow counterparts (\`ReadOnly\` + \`WriteOnly\`). All values are \`as const\` arrays for full type safety.
|
|
470
|
-
|
|
471
|
-
## \`withDefaults\` — composite presets
|
|
472
|
-
|
|
473
|
-
Wrap a composite with pre-applied defaults. Defaulted props become optional:
|
|
474
|
-
|
|
475
|
-
{{file:docs-snippets/src/with-defaults.ts}}
|
|
476
|
-
|
|
477
|
-
\`withDefaults\` preserves the original composite's identity — same \`_id\` and \`compositeName\`, no new registry entry.
|
|
478
|
-
|
|
479
|
-
### Computed defaults
|
|
480
|
-
|
|
481
|
-
\`withDefaults\` also accepts a function that receives the caller's props and returns defaults. This enables conditional logic without generating extra resources:
|
|
482
|
-
|
|
483
|
-
{{file:docs-snippets/src/computed-defaults.ts}}
|
|
484
|
-
|
|
485
|
-
Merge order: computed defaults are applied first, then user-provided props override them.
|
|
486
|
-
|
|
487
|
-
## \`propagate\` — shared properties
|
|
488
|
-
|
|
489
|
-
Attach properties that merge into every member during expansion:
|
|
490
|
-
|
|
491
|
-
{{file:docs-snippets/src/propagate.ts}}
|
|
492
|
-
|
|
493
|
-
Merge semantics:
|
|
494
|
-
- **Scalars** — member-specific value wins over shared
|
|
495
|
-
- **Arrays** (e.g. tags) — shared values prepended, member values appended
|
|
496
|
-
- **\`undefined\`** — stripped from shared props, never overwrites
|
|
497
|
-
|
|
498
|
-
## Nested stacks
|
|
499
|
-
|
|
500
|
-
:::caution
|
|
501
|
-
Nested stacks add deployment complexity and are not recommended for most projects. Prefer flat composites instead.
|
|
502
|
-
:::
|
|
503
|
-
|
|
504
|
-
When you need to split resources into a separate CloudFormation template, the lexicon supports nested stacks via \`nestedStack()\`. See the [Nested Stacks](../nested-stacks/) page for details.`,
|
|
505
|
-
},
|
|
506
|
-
{
|
|
507
|
-
slug: "nested-stacks",
|
|
508
|
-
title: "Nested Stacks",
|
|
509
|
-
sidebar: false,
|
|
510
|
-
description: "Splitting resources into child CloudFormation templates with automatic cross-stack reference wiring",
|
|
511
|
-
content: `import Diagram from '../../components/Diagram.astro';
|
|
512
|
-
|
|
513
|
-
CloudFormation nested stacks (\`AWS::CloudFormation::Stack\`) let you decompose large templates into smaller, reusable child templates. The AWS lexicon's \`nestedStack()\` function references a **child project directory** — a subdirectory that builds independently to a valid CloudFormation template.
|
|
514
|
-
|
|
515
|
-
:::caution[Consider alternatives first]
|
|
516
|
-
Nested stacks add deployment complexity: child templates must be uploaded to S3, rollbacks are all-or-nothing at the parent level, drift detection doesn't recurse into children, and debugging failures requires drilling into child stack events. For splitting a large project into separately-deployed pieces, prefer [Multi-Stack Projects](/chant/guide/multi-stack/) — each \`src/\` subdirectory becomes an independent stack with no parent orchestration and no S3 upload step. Nested stacks are supported for specific cases — exceeding CloudFormation's 500-resource limit inside a single deployable unit, or packaging reusable infrastructure for other teams to deploy as a black box — but are not the recommended default.
|
|
517
|
-
:::
|
|
518
|
-
|
|
519
|
-
<Diagram name="nested-stacks" alt="Parent and child project source directories producing separate CloudFormation templates, both uploaded to S3" caption="Nested stack source layout and output" />
|
|
520
|
-
|
|
521
|
-
## Project structure
|
|
522
|
-
|
|
523
|
-
A nested stack is a child project — a subdirectory with its own resource files and explicit \`stackOutput()\` declarations:
|
|
524
|
-
|
|
525
|
-
\`\`\`
|
|
526
|
-
src/
|
|
527
|
-
app.ts # parent resources
|
|
528
|
-
network/ # ← child project (nested stack)
|
|
529
|
-
vpc.ts # VPC, subnet, internet gateway, routing
|
|
530
|
-
security.ts # security group for Lambda
|
|
531
|
-
outputs.ts # declares cross-stack outputs
|
|
532
|
-
\`\`\`
|
|
533
|
-
|
|
534
|
-
## Declaring outputs in the child
|
|
535
|
-
|
|
536
|
-
Use \`stackOutput()\` to mark values that the parent can reference. Each \`stackOutput()\` becomes an entry in the child template's \`Outputs\` section:
|
|
537
|
-
|
|
538
|
-
{{file:../src/testdata/nested-stacks/network/outputs.ts}}
|
|
539
|
-
|
|
540
|
-
The child can be built independently:
|
|
541
|
-
|
|
542
|
-
\`\`\`bash
|
|
543
|
-
chant build src/network/ -o network.json
|
|
544
|
-
# Produces a standalone, valid CloudFormation template with Outputs
|
|
545
|
-
\`\`\`
|
|
546
|
-
|
|
547
|
-
## Referencing from the parent
|
|
548
|
-
|
|
549
|
-
Use \`nestedStack()\` in the parent to reference a child project directory. It returns an object with an \`outputs\` proxy for cross-stack references:
|
|
550
|
-
|
|
551
|
-
{{file:../src/testdata/nested-stacks/app.ts}}
|
|
552
|
-
|
|
553
|
-
\`network.outputs.subnetId\` produces a \`NestedStackOutputRef\` that serializes to \`{ "Fn::GetAtt": ["Network", "Outputs.SubnetId"] }\`.
|
|
554
|
-
|
|
555
|
-
## Build output
|
|
556
|
-
|
|
557
|
-
\`chant build\` produces multiple template files:
|
|
558
|
-
|
|
559
|
-
\`\`\`bash
|
|
560
|
-
chant build -o template.json
|
|
561
|
-
# Produces:
|
|
562
|
-
# template.json — parent template
|
|
563
|
-
# network.template.json — child template
|
|
564
|
-
\`\`\`
|
|
565
|
-
|
|
566
|
-
The parent template includes an \`AWS::CloudFormation::Stack\` resource pointing to the child:
|
|
567
|
-
|
|
568
|
-
\`\`\`json
|
|
569
|
-
"Network": {
|
|
570
|
-
"Type": "AWS::CloudFormation::Stack",
|
|
571
|
-
"Properties": {
|
|
572
|
-
"TemplateURL": { "Fn::Sub": "\${TemplateBasePath}/network.template.json" }
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
\`\`\`
|
|
576
|
-
|
|
577
|
-
## \`TemplateBasePath\` parameter
|
|
578
|
-
|
|
579
|
-
Every parent template gets a \`TemplateBasePath\` parameter (default \`"."\`) that controls where CloudFormation looks for child templates:
|
|
580
|
-
|
|
581
|
-
\`\`\`bash
|
|
582
|
-
# Local dev — default "." works with rain and similar tools
|
|
583
|
-
chant build -o template.json
|
|
584
|
-
|
|
585
|
-
# Production — override with S3 URL
|
|
586
|
-
aws cloudformation deploy \\
|
|
587
|
-
--template-file template.json \\
|
|
588
|
-
--stack-name my-stack \\
|
|
589
|
-
--parameter-overrides TemplateBasePath=https://my-bucket.s3.amazonaws.com/templates
|
|
590
|
-
\`\`\`
|
|
591
|
-
|
|
592
|
-
Child templates also receive the \`TemplateBasePath\` parameter so it propagates through all nesting levels.
|
|
593
|
-
|
|
594
|
-
All child template files must be uploaded alongside the parent template (or to the S3 path specified by \`TemplateBasePath\`).
|
|
595
|
-
|
|
596
|
-
## Explicit parameters
|
|
597
|
-
|
|
598
|
-
Pass CloudFormation Parameters to child stacks with the \`parameters\` option:
|
|
599
|
-
|
|
600
|
-
\`\`\`typescript
|
|
601
|
-
import { nestedStack } from "@intentius/chant-lexicon-aws";
|
|
602
|
-
|
|
603
|
-
const network = nestedStack("network", import.meta.dirname + "/network", {
|
|
604
|
-
parameters: { Environment: "prod", CidrBlock: "10.0.0.0/16" },
|
|
605
|
-
});
|
|
606
|
-
\`\`\`
|
|
607
|
-
|
|
608
|
-
## Recursive nesting
|
|
609
|
-
|
|
610
|
-
Child projects can themselves reference grandchild projects. Each level produces its own template file:
|
|
611
|
-
|
|
612
|
-
\`\`\`
|
|
613
|
-
src/
|
|
614
|
-
app.ts
|
|
615
|
-
infra/
|
|
616
|
-
network/
|
|
617
|
-
vpc.ts
|
|
618
|
-
outputs.ts
|
|
619
|
-
database/
|
|
620
|
-
cluster.ts
|
|
621
|
-
outputs.ts
|
|
622
|
-
\`\`\`
|
|
623
|
-
|
|
624
|
-
The build pipeline detects circular references and reports an error if child A references child B which references child A.
|
|
625
|
-
|
|
626
|
-
## Lint rules
|
|
627
|
-
|
|
628
|
-
Three lint rules help catch common nested stack issues:
|
|
629
|
-
|
|
630
|
-
| Rule | Severity | Description |
|
|
631
|
-
|------|----------|-------------|
|
|
632
|
-
| **WAW013** | error | Child project has no \`stackOutput()\` exports — parent can't reference anything |
|
|
633
|
-
| **WAW014** | warning | \`nestedStack()\` outputs never referenced from parent — could be a separate build |
|
|
634
|
-
| **WAW015** | error | Circular project references |
|
|
635
|
-
|
|
636
|
-
## When to use nested stacks
|
|
637
|
-
|
|
638
|
-
Most splitting use cases are better served by other mechanisms:
|
|
639
|
-
|
|
640
|
-
- **Splitting a large project into separately-deployed pieces** → [Multi-Stack Projects](/chant/guide/multi-stack/). Organize \`src/\` into subdirectories — each becomes an independent stack, deployed on its own, with cross-stack references resolved via standard CloudFormation \`Export\`/\`ImportValue\`. No parent template, no S3 upload of children, no \`TemplateBasePath\` parameter.
|
|
641
|
-
- **Reusing resource patterns within a single template** → [Composites](../composites/). Composites expand into the same template and deploy atomically — they're about DRY, not splitting.
|
|
642
|
-
|
|
643
|
-
**Use nested stacks only when:**
|
|
644
|
-
- A single deployable unit exceeds CloudFormation's 500-resource limit
|
|
645
|
-
- You're packaging reusable infrastructure for other teams to consume as a black box (the parent-child relationship is load-bearing)
|
|
646
|
-
- You need an orchestrator parent that coordinates child lifecycles via CloudFormation Parameters and Outputs specifically`,
|
|
647
|
-
},
|
|
648
|
-
{
|
|
649
|
-
slug: "lint-rules",
|
|
650
|
-
title: "Lint Rules",
|
|
651
|
-
description: "Built-in lint rules and post-synth checks for AWS CloudFormation",
|
|
652
|
-
content: `The AWS lexicon ships lint rules that run during \`chant lint\` and post-synth checks that validate the serialized CloudFormation output after \`chant build\`.
|
|
653
|
-
|
|
654
|
-
This page explains the most commonly hit rules in depth. For the complete list —
|
|
655
|
-
every rule the lexicon registers, generated from the registration itself so it
|
|
656
|
-
cannot fall behind — see [All Rules](../rules/). The security-hardening rules
|
|
657
|
-
(WAW032 onward) also carry remediation guidance and upstream references in the
|
|
658
|
-
[audit rules reference](/chant/lint-rules/audit-rules/).
|
|
659
|
-
|
|
660
|
-
## Lint rules
|
|
661
|
-
|
|
662
|
-
Lint rules analyze your TypeScript source code before build.
|
|
663
|
-
|
|
664
|
-
### WAW001 — Hardcoded Region
|
|
665
|
-
|
|
666
|
-
**Severity:** warning | **Category:** security
|
|
667
|
-
|
|
668
|
-
Flags hardcoded AWS region strings like \`us-east-1\`. Use \`AWS.Region\` instead so templates are portable across regions.
|
|
669
|
-
|
|
670
|
-
**Bad** — triggers WAW001:
|
|
671
|
-
|
|
672
|
-
{{file:docs-snippets/src/lint-waw001-bad.ts}}
|
|
673
|
-
|
|
674
|
-
**Good** — uses \`AWS.Region\`:
|
|
675
|
-
|
|
676
|
-
{{file:docs-snippets/src/lint-waw001-good.ts}}
|
|
677
|
-
|
|
678
|
-
### WAW006 — S3 Bucket Encryption
|
|
679
|
-
|
|
680
|
-
**Severity:** warning | **Category:** security
|
|
681
|
-
|
|
682
|
-
Flags S3 buckets that don't configure server-side encryption. AWS recommends enabling encryption on all buckets.
|
|
683
|
-
|
|
684
|
-
**Bad** — triggers WAW006:
|
|
685
|
-
|
|
686
|
-
{{file:docs-snippets/src/lint-waw006-bad.ts}}
|
|
687
|
-
|
|
688
|
-
**Good** — encryption configured:
|
|
689
|
-
|
|
690
|
-
{{file:docs-snippets/src/lint-waw006-good.ts}}
|
|
691
|
-
|
|
692
|
-
### WAW009 — IAM Wildcard Resource
|
|
693
|
-
|
|
694
|
-
**Severity:** warning | **Category:** security
|
|
695
|
-
|
|
696
|
-
Flags IAM policy statements that use \`"Resource": "*"\`. Prefer scoped resource ARNs following the principle of least privilege.
|
|
697
|
-
|
|
698
|
-
**Bad** — triggers WAW009:
|
|
699
|
-
|
|
700
|
-
{{file:docs-snippets/src/lint-waw009-bad.ts}}
|
|
701
|
-
|
|
702
|
-
**Good** — scoped ARN:
|
|
703
|
-
|
|
704
|
-
{{file:docs-snippets/src/lint-waw009-good.ts}}
|
|
705
|
-
|
|
706
|
-
IAM policy documents use PascalCase keys (\`Effect\`, \`Action\`, \`Resource\`) matching the IAM JSON Policy Language spec. The \`PolicyDocument\` and \`IamPolicyStatement\` types provide full autocomplete for these fields.
|
|
707
|
-
|
|
708
|
-
## Post-synth checks
|
|
709
|
-
|
|
710
|
-
Post-synth checks run against the serialized CloudFormation JSON after build. They catch issues that are only visible in the final template.
|
|
711
|
-
|
|
712
|
-
### COR020 — Circular Resource Dependency
|
|
713
|
-
|
|
714
|
-
Detects cycles in the resource dependency graph built from \`Ref\`, \`Fn::GetAtt\`, and \`DependsOn\` entries. Circular dependencies cause CloudFormation deployments to fail.
|
|
715
|
-
|
|
716
|
-
### EXT001 — Extension Constraint Violation
|
|
717
|
-
|
|
718
|
-
Validates cross-property constraints from CloudFormation's cfn-lint extension schemas. For example, an EC2 instance might require \`SubnetId\` when \`NetworkInterfaces\` is not set.
|
|
719
|
-
|
|
720
|
-
### WAW010 — Redundant DependsOn
|
|
721
|
-
|
|
722
|
-
Flags \`DependsOn\` entries where the target resource is already referenced via \`Ref\` or \`Fn::GetAtt\` in the resource's properties. CloudFormation automatically creates dependencies for these references, making the explicit \`DependsOn\` unnecessary.
|
|
723
|
-
|
|
724
|
-
### WAW011 — Deprecated Lambda Runtime
|
|
725
|
-
|
|
726
|
-
Flags Lambda functions using deprecated or approaching-end-of-life runtimes (e.g. \`nodejs16.x\`, \`python3.8\`). Using deprecated runtimes prevents function updates and may cause deployment failures.
|
|
727
|
-
|
|
728
|
-
### WAW013 — No Stack Outputs
|
|
729
|
-
|
|
730
|
-
**Severity:** error | **Category:** correctness
|
|
731
|
-
|
|
732
|
-
Flags child projects (nested stacks) that have no \`stackOutput()\` exports. Without outputs, the parent stack can't reference any values from the child — either add \`stackOutput()\` declarations or remove the \`nestedStack()\` reference.
|
|
733
|
-
|
|
734
|
-
### WAW014 — Unreferenced Stack Outputs
|
|
735
|
-
|
|
736
|
-
**Severity:** warning | **Category:** style
|
|
737
|
-
|
|
738
|
-
Flags \`nestedStack()\` references whose outputs are never used from the parent. If no cross-stack references exist, the child project could just be built and deployed independently.
|
|
739
|
-
|
|
740
|
-
### WAW015 — Circular Project References
|
|
741
|
-
|
|
742
|
-
**Severity:** error | **Category:** correctness
|
|
743
|
-
|
|
744
|
-
Detects circular references between child projects (e.g. project A references project B which references project A). Circular project dependencies cause infinite build recursion.
|
|
745
|
-
|
|
746
|
-
### WAW016 — Deprecated Property Usage
|
|
747
|
-
|
|
748
|
-
**Severity:** warning | **Category:** correctness
|
|
749
|
-
|
|
750
|
-
Flags properties marked as deprecated in the CloudFormation Registry. Data comes from two sources: the explicit \`deprecatedProperties\` array in the Registry schema, and description text mining (keywords like "deprecated", "legacy", "no longer recommended").
|
|
751
|
-
|
|
752
|
-
For example, \`AccessControl\` on \`AWS::S3::Bucket\` is a legacy property — use a bucket policy to grant access instead.
|
|
753
|
-
|
|
754
|
-
\`\`\`
|
|
755
|
-
WAW016: Resource "MyBucket" (AWS::S3::Bucket) uses deprecated property "AccessControl" — consider alternatives
|
|
756
|
-
\`\`\`
|
|
757
|
-
|
|
758
|
-
### WAW017 — Missing Tags on Taggable Resource
|
|
759
|
-
|
|
760
|
-
**Severity:** info | **Category:** best practice
|
|
761
|
-
|
|
762
|
-
Flags resources that support tagging but have no \`Tags\` property set. Tags are important for cost allocation, compliance, and operational visibility. The check uses the \`tagging\` metadata from the CloudFormation Registry to determine which resources are taggable.
|
|
763
|
-
|
|
764
|
-
\`\`\`
|
|
765
|
-
WAW017: Resource "MyBucket" (AWS::S3::Bucket) supports tagging but has no Tags — consider adding tags for cost allocation and compliance
|
|
766
|
-
\`\`\`
|
|
767
|
-
|
|
768
|
-
### WAW029 — Invalid DependsOn Target
|
|
769
|
-
|
|
770
|
-
**Severity:** error | **Category:** correctness
|
|
771
|
-
|
|
772
|
-
Flags \`DependsOn\` entries that reference a non-existent resource (typo or deleted resource) or that create a self-reference. Both cases cause CloudFormation deployments to fail immediately.
|
|
773
|
-
|
|
774
|
-
\`\`\`
|
|
775
|
-
WAW029: Resource "MyService" has DependsOn "MyBukcet" which does not exist in the template
|
|
776
|
-
WAW029: Resource "MyBucket" has a DependsOn on itself — self-references are invalid
|
|
777
|
-
\`\`\`
|
|
778
|
-
|
|
779
|
-
### WAW030 — Missing DependsOn for Known Patterns
|
|
780
|
-
|
|
781
|
-
**Severity:** warning | **Category:** best practice
|
|
782
|
-
|
|
783
|
-
Flags resources that are likely missing a required explicit \`DependsOn\` based on well-known CloudFormation ordering requirements:
|
|
784
|
-
|
|
785
|
-
- **ECS Service + Listener**: An ECS Service with \`LoadBalancers\` should depend on the ALB Listener so the target group is fully configured before the service starts registering tasks.
|
|
786
|
-
- **EC2 Route + VPCGatewayAttachment**: A Route using a \`GatewayId\` should depend on the VPCGatewayAttachment so the gateway is attached to the VPC before the route is created.
|
|
787
|
-
- **API Gateway Deployment + Method**: A Deployment only references \`RestApiId\` — it needs an explicit \`DependsOn\` on its Methods or CloudFormation may create the deployment before any methods exist.
|
|
788
|
-
- **API Gateway V2 Deployment + Route**: Same as above for HTTP APIs — a V2 Deployment needs \`DependsOn\` on its Routes.
|
|
789
|
-
- **DynamoDB Table + ScalableTarget**: A ScalableTarget with \`ServiceNamespace: "dynamodb"\` references the table by string \`ResourceId\`, not \`Ref\` — it needs \`DependsOn\` so the table exists before scaling is registered.
|
|
790
|
-
- **ECS Service + ScalableTarget**: A ScalableTarget with \`ServiceNamespace: "ecs"\` references the service by string — it needs \`DependsOn\` so the ECS Service exists first.
|
|
791
|
-
|
|
792
|
-
\`\`\`
|
|
793
|
-
WAW030: ECS Service "MyService" has LoadBalancers but no DependsOn on a Listener
|
|
794
|
-
WAW030: Route "PublicRoute" uses a Gateway but has no dependency on VPCGatewayAttachment
|
|
795
|
-
WAW030: API Gateway Deployment "MyDeployment" has no DependsOn on any Method
|
|
796
|
-
WAW030: ScalableTarget "MyTarget" targets DynamoDB but has no DependsOn on any Table
|
|
797
|
-
\`\`\`
|
|
798
|
-
|
|
799
|
-
### WAW018 — S3 Bucket Missing Public Access Block
|
|
800
|
-
|
|
801
|
-
**Severity:** error | **Category:** security
|
|
802
|
-
|
|
803
|
-
Flags S3 buckets without a \`PublicAccessBlockConfiguration\`. Without an explicit public access block, the bucket may be publicly accessible. Always set \`BlockPublicAcls\`, \`BlockPublicPolicy\`, \`IgnorePublicAcls\`, and \`RestrictPublicBuckets\` to \`true\`.
|
|
804
|
-
|
|
805
|
-
### WAW019 — Security Group Unrestricted Ingress on Sensitive Ports
|
|
806
|
-
|
|
807
|
-
**Severity:** error | **Category:** security
|
|
808
|
-
|
|
809
|
-
Flags security group ingress rules that allow unrestricted access (\`0.0.0.0/0\` or \`::/0\`) on sensitive ports (22, 3389, 3306, 5432, 1433, 6379, 27017). Restrict ingress to known CIDR ranges or security groups.
|
|
810
|
-
|
|
811
|
-
### WAW020 — IAM Policy Uses Wildcard Action
|
|
812
|
-
|
|
813
|
-
**Severity:** warning | **Category:** security
|
|
814
|
-
|
|
815
|
-
Flags IAM policy statements that use wildcard actions (\`"Action": "*"\` or \`"Action": "s3:*"\`). Use specific action names following the principle of least privilege.
|
|
816
|
-
|
|
817
|
-
### WAW021 — RDS Storage Not Encrypted
|
|
818
|
-
|
|
819
|
-
**Severity:** error | **Category:** security
|
|
820
|
-
|
|
821
|
-
Flags RDS instances without \`StorageEncrypted: true\`. All RDS instances should encrypt data at rest to meet compliance and security requirements.
|
|
822
|
-
|
|
823
|
-
### WAW022 — Lambda Not in VPC
|
|
824
|
-
|
|
825
|
-
**Severity:** warning | **Category:** security
|
|
826
|
-
|
|
827
|
-
Flags Lambda functions without a \`VpcConfig\`. Functions that access internal resources (databases, caches, internal APIs) should run inside a VPC. Functions that only call public APIs can safely skip VPC configuration.
|
|
828
|
-
|
|
829
|
-
### WAW023 — CloudFront Without WAF
|
|
830
|
-
|
|
831
|
-
**Severity:** warning | **Category:** security
|
|
832
|
-
|
|
833
|
-
Flags CloudFront distributions without a \`WebACLId\`. Attaching a WAF web ACL protects your distribution from common web exploits and bots.
|
|
834
|
-
|
|
835
|
-
### WAW024 — ALB Without Access Logging
|
|
836
|
-
|
|
837
|
-
**Severity:** warning | **Category:** best practice
|
|
838
|
-
|
|
839
|
-
Flags Application Load Balancers without access logging enabled. Enable \`access_logs.s3.enabled\` to capture request logs for debugging and compliance.
|
|
840
|
-
|
|
841
|
-
### WAW025 — SNS Topic Not Encrypted
|
|
842
|
-
|
|
843
|
-
**Severity:** warning | **Category:** security
|
|
844
|
-
|
|
845
|
-
Flags SNS topics without \`KmsMasterKeyId\`. Encrypting topics at rest protects sensitive notification payloads.
|
|
846
|
-
|
|
847
|
-
### WAW026 — SQS Queue Not Encrypted
|
|
848
|
-
|
|
849
|
-
**Severity:** warning | **Category:** security
|
|
850
|
-
|
|
851
|
-
Flags SQS queues without \`KmsMasterKeyId\` or \`SqsManagedSseEnabled\`. Encrypting queues at rest protects sensitive message payloads.
|
|
852
|
-
|
|
853
|
-
### WAW027 — DynamoDB Missing Point-in-Time Recovery
|
|
854
|
-
|
|
855
|
-
**Severity:** info | **Category:** best practice
|
|
856
|
-
|
|
857
|
-
Flags DynamoDB tables without \`PointInTimeRecoverySpecification.PointInTimeRecoveryEnabled\` set to \`true\`. Point-in-time recovery provides continuous backups and protects against accidental writes or deletes.
|
|
858
|
-
|
|
859
|
-
### WAW028 — EBS Volume Not Encrypted
|
|
860
|
-
|
|
861
|
-
**Severity:** warning | **Category:** security
|
|
862
|
-
|
|
863
|
-
Flags EBS volumes without \`Encrypted: true\`. All EBS volumes should encrypt data at rest for compliance and security.
|
|
864
|
-
|
|
865
|
-
### WAW031 — EKS Addon Missing ServiceAccountRoleArn
|
|
866
|
-
|
|
867
|
-
**Severity:** warning | **Category:** correctness
|
|
868
|
-
|
|
869
|
-
Flags EKS addons that require an IRSA role but don't have \`ServiceAccountRoleArn\` set. Without an IRSA role, the addon pods can't authenticate to AWS APIs and the addon hangs in CREATING status. Known addons that require IRSA: \`aws-ebs-csi-driver\`, \`aws-efs-csi-driver\`, \`adot\`, \`amazon-cloudwatch-observability\`.
|
|
870
|
-
|
|
871
|
-
\`\`\`
|
|
872
|
-
WAW031: EKS Addon "EbsCsiAddon" (aws-ebs-csi-driver) has no ServiceAccountRoleArn — it needs an IRSA role for EBS API access
|
|
873
|
-
\`\`\`
|
|
874
|
-
|
|
875
|
-
## Running lint
|
|
876
|
-
|
|
877
|
-
\`\`\`bash
|
|
878
|
-
# Lint your chant project
|
|
879
|
-
chant lint
|
|
880
|
-
|
|
881
|
-
# Lint with auto-fix where supported
|
|
882
|
-
chant lint --fix
|
|
883
|
-
\`\`\`
|
|
884
|
-
|
|
885
|
-
To suppress a rule on a specific line:
|
|
886
|
-
|
|
887
|
-
\`\`\`typescript
|
|
888
|
-
// chant-disable-next-line WAW001
|
|
889
|
-
const endpoint = "s3.us-east-1.amazonaws.com";
|
|
890
|
-
\`\`\`
|
|
891
|
-
|
|
892
|
-
To suppress globally in \`chant.config.ts\`:
|
|
893
|
-
|
|
894
|
-
\`\`\`typescript
|
|
895
|
-
export default {
|
|
896
|
-
lint: {
|
|
897
|
-
rules: {
|
|
898
|
-
WAW001: "off",
|
|
899
|
-
},
|
|
900
|
-
},
|
|
901
|
-
};
|
|
902
|
-
\`\`\`
|
|
903
|
-
|
|
904
|
-
See also [Custom Lint Rules](../custom-rules/) for writing project-specific rules.`,
|
|
905
|
-
},
|
|
906
|
-
{
|
|
907
|
-
slug: "custom-rules",
|
|
908
|
-
title: "Custom Lint Rules",
|
|
909
|
-
description: "Writing and registering project-specific lint rules for AWS CloudFormation",
|
|
910
|
-
content: `Chant's lint engine runs TypeScript AST visitors. Write project-specific rules that enforce domain conventions.
|
|
911
|
-
|
|
912
|
-
## Anatomy of a lint rule
|
|
913
|
-
|
|
914
|
-
The lambda-api example includes a full custom rule implementation:
|
|
915
|
-
|
|
916
|
-
{{file:lambda-api/src/lint/api-timeout.ts}}
|
|
917
|
-
|
|
918
|
-
The \`check\` function receives a \`LintContext\` containing the TypeScript \`sourceFile\` and returns an array of diagnostics with file, line, column, and message.
|
|
919
|
-
|
|
920
|
-
## Registering custom rules
|
|
921
|
-
|
|
922
|
-
Add a \`chant.config.ts\` to your project:
|
|
923
|
-
|
|
924
|
-
{{file:lambda-api/src/chant.config.ts}}
|
|
925
|
-
|
|
926
|
-
The \`plugins\` array accepts relative paths. Each plugin module should export a \`LintRule\` object.`,
|
|
927
|
-
},
|
|
928
|
-
{
|
|
929
|
-
slug: "examples",
|
|
930
|
-
title: "Examples",
|
|
931
|
-
description: "Walkthrough of the AWS CloudFormation lexicon examples",
|
|
932
|
-
content: `Runnable examples live in the lexicon's \`examples/\` directory — one per built-in composite. Clone the repo and try them:
|
|
933
|
-
|
|
934
|
-
\`\`\`bash
|
|
935
|
-
cd examples/lambda-function
|
|
936
|
-
npm install
|
|
937
|
-
chant build # produces CloudFormation JSON
|
|
938
|
-
chant lint # runs lint rules
|
|
939
|
-
npx vitest run # run the tests
|
|
940
|
-
\`\`\`
|
|
941
|
-
|
|
942
|
-
## Lambda Function
|
|
943
|
-
|
|
944
|
-
\`examples/lambda-function/\` — the simplest possible example. Uses \`LambdaNode\` to create a basic Lambda.
|
|
945
|
-
|
|
946
|
-
{{file:lambda-function/src/main.ts}}
|
|
947
|
-
|
|
948
|
-
Produces 2 CloudFormation resources: IAM Role + Lambda Function.
|
|
949
|
-
|
|
950
|
-
## Lambda S3
|
|
951
|
-
|
|
952
|
-
\`examples/lambda-s3/\` — Lambda that lists S3 objects using the \`LambdaS3\` composite.
|
|
953
|
-
|
|
954
|
-
{{file:lambda-s3/src/main.ts}}
|
|
955
|
-
|
|
956
|
-
Produces 3 resources: S3 Bucket (encrypted, public access blocked) + IAM Role (with S3 read policy) + Lambda Function. The \`BUCKET_NAME\` environment variable is auto-injected.
|
|
957
|
-
|
|
958
|
-
## Lambda DynamoDB
|
|
959
|
-
|
|
960
|
-
\`examples/lambda-dynamodb/\` — Lambda that reads/writes DynamoDB items using the \`LambdaDynamoDB\` composite.
|
|
961
|
-
|
|
962
|
-
{{file:lambda-dynamodb/src/main.ts}}
|
|
963
|
-
|
|
964
|
-
Produces 3 resources: DynamoDB Table + IAM Role (with DynamoDB read/write policy) + Lambda Function. The \`TABLE_NAME\` environment variable is auto-injected.
|
|
965
|
-
|
|
966
|
-
## Lambda SQS
|
|
967
|
-
|
|
968
|
-
\`examples/lambda-sqs/\` — Lambda processing messages from an SQS queue using the \`LambdaSqs\` composite.
|
|
969
|
-
|
|
970
|
-
{{file:lambda-sqs/src/main.ts}}
|
|
971
|
-
|
|
972
|
-
Produces 4 resources: SQS Queue + IAM Role (with SQS receive policy) + Lambda Function + EventSourceMapping.
|
|
973
|
-
|
|
974
|
-
## Lambda SNS
|
|
975
|
-
|
|
976
|
-
\`examples/lambda-sns/\` — Lambda triggered by SNS notifications using the \`LambdaSns\` composite.
|
|
977
|
-
|
|
978
|
-
{{file:lambda-sns/src/main.ts}}
|
|
979
|
-
|
|
980
|
-
Produces 5 resources: SNS Topic + IAM Role + Lambda Function + SNS Subscription + Lambda Permission.
|
|
981
|
-
|
|
982
|
-
## Lambda Scheduled
|
|
983
|
-
|
|
984
|
-
\`examples/lambda-scheduled/\` — Lambda on a cron schedule using the \`LambdaScheduled\` composite.
|
|
985
|
-
|
|
986
|
-
{{file:lambda-scheduled/src/main.ts}}
|
|
987
|
-
|
|
988
|
-
Produces 4 resources: IAM Role + Lambda Function + EventBridge Rule + Lambda Permission.
|
|
989
|
-
|
|
990
|
-
## Lambda EventBridge
|
|
991
|
-
|
|
992
|
-
\`examples/lambda-eventbridge/\` — Lambda triggered by EventBridge events using the \`LambdaEventBridge\` composite.
|
|
993
|
-
|
|
994
|
-
{{file:lambda-eventbridge/src/main.ts}}
|
|
995
|
-
|
|
996
|
-
Produces 4 resources: EventBridge Rule + IAM Role + Lambda Function + Lambda Permission.
|
|
997
|
-
|
|
998
|
-
## VPC
|
|
999
|
-
|
|
1000
|
-
\`examples/vpc/\` — production-ready VPC using the \`VpcDefault\` composite.
|
|
1001
|
-
|
|
1002
|
-
{{file:vpc/src/main.ts}}
|
|
1003
|
-
|
|
1004
|
-
Produces 17 CloudFormation resources: VPC, Internet Gateway, 2 public + 2 private subnets, NAT Gateway with EIP, route tables, routes, and associations.
|
|
1005
|
-
|
|
1006
|
-
## Fargate ALB
|
|
1007
|
-
|
|
1008
|
-
\`examples/fargate-alb/\` — Fargate service behind an ALB, consuming a VPC. Demonstrates composite composability.
|
|
1009
|
-
|
|
1010
|
-
{{file:fargate-alb/src/network.ts}}
|
|
1011
|
-
|
|
1012
|
-
{{file:fargate-alb/src/service.ts}}
|
|
1013
|
-
|
|
1014
|
-
Produces 28 CloudFormation resources: 17 from VpcDefault + 11 from FargateAlb (ECS Cluster, execution/task roles, log group, task definition, security groups, ALB, target group, listener, and ECS service).
|
|
1015
|
-
|
|
1016
|
-
## Multi-Service ALB
|
|
1017
|
-
|
|
1018
|
-
\`examples/multi-service-alb/\` — multiple Fargate services behind a single shared ALB using \`AlbShared\` + \`FargateService\`.
|
|
1019
|
-
|
|
1020
|
-
{{file:multi-service-alb/src/shared.ts}}
|
|
1021
|
-
|
|
1022
|
-
{{file:multi-service-alb/src/services.ts}}
|
|
1023
|
-
|
|
1024
|
-
Produces 36 CloudFormation resources: 17 from VpcDefault + 5 from AlbShared + 7×2 from FargateService (task role, log group, task definition, task security group, target group, listener rule, and ECS service per service).
|
|
1025
|
-
|
|
1026
|
-
## Shared ALB (Separate Projects)
|
|
1027
|
-
|
|
1028
|
-
\`examples/shared-alb/\`, \`examples/shared-alb-api/\`, \`examples/shared-alb-ui/\` — the same multi-service ALB pattern as above, but split across separate CloudFormation stacks for independent deployment.
|
|
1029
|
-
|
|
1030
|
-
### Infra stack
|
|
1031
|
-
|
|
1032
|
-
The shared-alb stack contains VPC, ALB, ECS cluster, and ECR repositories. It exports outputs that service stacks consume as parameters:
|
|
1033
|
-
|
|
1034
|
-
{{file:shared-alb/src/alb.ts}}
|
|
1035
|
-
|
|
1036
|
-
{{file:shared-alb/src/ecr.ts}}
|
|
1037
|
-
|
|
1038
|
-
{{file:shared-alb/src/outputs.ts}}
|
|
1039
|
-
|
|
1040
|
-
### Service stacks
|
|
1041
|
-
|
|
1042
|
-
Each service stack receives shared infrastructure as parameters and deploys a single Fargate service:
|
|
1043
|
-
|
|
1044
|
-
{{file:shared-alb-api/src/params.ts}}
|
|
1045
|
-
|
|
1046
|
-
{{file:shared-alb-api/src/service.ts}}
|
|
1047
|
-
|
|
1048
|
-
**Deployment pattern:**
|
|
1049
|
-
|
|
1050
|
-
1. Deploy the infra stack first — creates VPC, ALB, ECS cluster, and ECR repos
|
|
1051
|
-
2. Deploy each service stack independently with \`--parameter-overrides\` mapping infra outputs to service parameters
|
|
1052
|
-
3. Each service gets its own \`image\` parameter for CI/CD pipelines to inject the container image URI
|
|
1053
|
-
|
|
1054
|
-
The separate-project pattern enables independent team ownership and deployment cadences. See the [GitLab CI/CD lexicon examples](/chant/lexicons/gitlab/examples/) for pipeline definitions that automate this workflow.
|
|
1055
|
-
|
|
1056
|
-
## Lambda API (Custom Composite)
|
|
1057
|
-
|
|
1058
|
-
\`examples/lambda-api/\` — demonstrates building your own composite factory with presets and a custom lint rule. This is the only example that teaches custom composite authoring.
|
|
1059
|
-
|
|
1060
|
-
\`\`\`
|
|
1061
|
-
src/
|
|
1062
|
-
├── chant.config.ts # Lint config: strict preset + custom plugin
|
|
1063
|
-
├── defaults.ts # Encryption, versioning, access block, Lambda trust policy
|
|
1064
|
-
├── data-bucket.ts # S3 bucket
|
|
1065
|
-
├── lambda-api.ts # Composite factory + SecureApi/HighMemoryApi presets
|
|
1066
|
-
├── health-api.ts # SecureApi — minimal health check
|
|
1067
|
-
├── upload-api.ts # SecureApi + S3 PutObject policy
|
|
1068
|
-
├── process-api.ts # HighMemoryApi + S3 read/write policy
|
|
1069
|
-
└── lint/
|
|
1070
|
-
└── api-timeout.ts # Custom WAW012 rule
|
|
1071
|
-
\`\`\`
|
|
1072
|
-
|
|
1073
|
-
**Patterns demonstrated:**
|
|
1074
|
-
|
|
1075
|
-
- **Custom composites** — \`LambdaApi\` groups Role + Function + Permission into a reusable unit (see [Composites](../composites/))
|
|
1076
|
-
- **Composite presets** — \`SecureApi\` (low memory, short timeout) and \`HighMemoryApi\` (high memory, longer timeout)
|
|
1077
|
-
- **Custom lint rule** — \`api-timeout.ts\` enforces API Gateway's 29-second timeout limit (see [Custom Lint Rules](../custom-rules/))
|
|
1078
|
-
|
|
1079
|
-
The example produces 10 CloudFormation resources: 1 S3 bucket + 3 composites × 3 members each.
|
|
1080
|
-
|
|
1081
|
-
## RDS Instance
|
|
1082
|
-
|
|
1083
|
-
\`examples/rds-postgres/\` — production RDS PostgreSQL instance using the \`RdsInstance\` composite with VPC networking and SSM parameter references.
|
|
1084
|
-
|
|
1085
|
-
{{file:rds-postgres/src/params.ts}}
|
|
1086
|
-
|
|
1087
|
-
{{file:rds-postgres/src/network.ts}}
|
|
1088
|
-
|
|
1089
|
-
{{file:rds-postgres/src/database.ts}}
|
|
1090
|
-
|
|
1091
|
-
Produces a complete RDS stack: VPC infrastructure (from \`VpcDefault\`), DB subnet group, security group, and RDS instance with encrypted storage.`,
|
|
1092
|
-
},
|
|
1093
|
-
{
|
|
1094
|
-
slug: "skills",
|
|
1095
|
-
title: "AI Skills",
|
|
1096
|
-
description: "AI agent skills bundled with the AWS CloudFormation lexicon",
|
|
1097
|
-
content: `The AWS lexicon ships an AI skill called **chant-aws** that teaches AI coding agents (like Claude Code) how to build, validate, and deploy CloudFormation templates from a chant project.
|
|
1098
|
-
|
|
1099
|
-
## What are skills?
|
|
1100
|
-
|
|
1101
|
-
Skills are structured markdown documents bundled with a lexicon. When an AI agent works in a chant project, it discovers and loads relevant skills automatically — giving it operational knowledge about the deployment workflow without requiring the user to explain each step.
|
|
1102
|
-
|
|
1103
|
-
## Installation
|
|
1104
|
-
|
|
1105
|
-
When you scaffold a new project with \`chant init --lexicon aws\`, the skill is installed to \`skills/chant-aws/SKILL.md\` for automatic discovery by Claude Code.
|
|
1106
|
-
|
|
1107
|
-
For existing projects, create the file manually:
|
|
1108
|
-
|
|
1109
|
-
\`\`\`
|
|
1110
|
-
.claude/
|
|
1111
|
-
skills/
|
|
1112
|
-
chant-aws/
|
|
1113
|
-
SKILL.md # skill content (see below)
|
|
1114
|
-
\`\`\`
|
|
1115
|
-
|
|
1116
|
-
## Skill: chant-aws
|
|
1117
|
-
|
|
1118
|
-
The \`chant-aws\` skill covers the full deployment lifecycle:
|
|
1119
|
-
|
|
1120
|
-
- **Build** — \`chant build src/ --output stack.json\`
|
|
1121
|
-
- **Validate** — \`chant lint src/\` + \`aws cloudformation validate-template\`
|
|
1122
|
-
- **Deploy** — \`aws cloudformation deploy\` with capabilities
|
|
1123
|
-
- **Update** — change sets for preview, or direct deploy
|
|
1124
|
-
- **Delete** — \`aws cloudformation delete-stack\`
|
|
1125
|
-
- **Status** — \`describe-stacks\` and \`describe-stack-events\`
|
|
1126
|
-
- **Troubleshooting** — event inspection, rollback recovery, drift detection
|
|
1127
|
-
|
|
1128
|
-
The skill is invocable as a slash command: \`/chant-aws\`
|
|
1129
|
-
|
|
1130
|
-
## MCP integration
|
|
1131
|
-
|
|
1132
|
-
The lexicon also provides MCP (Model Context Protocol) tools and resources that AI agents can use programmatically:
|
|
1133
|
-
|
|
1134
|
-
| MCP tool | Description |
|
|
1135
|
-
|----------|-------------|
|
|
1136
|
-
| \`build\` | Build the chant project |
|
|
1137
|
-
| \`lint\` | Run lint rules |
|
|
1138
|
-
| \`explain\` | Summarize project resources |
|
|
1139
|
-
| \`scaffold\` | Generate starter files |
|
|
1140
|
-
| \`search\` | Search available resource types |
|
|
1141
|
-
| \`aws:diff\` | Compare current build output against previous |
|
|
1142
|
-
|
|
1143
|
-
| MCP resource | Description |
|
|
1144
|
-
|--------------|-------------|
|
|
1145
|
-
| \`resource-catalog\` | JSON list of all supported CloudFormation resource types |
|
|
1146
|
-
| \`examples/basic-stack\` | Example stack with S3 bucket and IAM role |`,
|
|
1147
|
-
},
|
|
1148
|
-
],
|
|
1149
|
-
sidebarExtra: [
|
|
1150
|
-
{ label: "Deploying to EKS", slug: "eks-kubernetes" },
|
|
1151
|
-
{ label: "Nested Stacks", slug: "nested-stacks" },
|
|
1152
|
-
],
|
|
1153
121
|
};
|
|
1154
122
|
|
|
1155
123
|
log("Generating AWS documentation...");
|