Skip to content

feat(examples): set cross-stack reference strength explicitly to weak - #412

Open
laazyj wants to merge 1 commit into
mainfrom
claude/composurecdk-issue-341-f0mfkj
Open

feat(examples): set cross-stack reference strength explicitly to weak#412
laazyj wants to merge 1 commit into
mainfrom
claude/composurecdk-issue-341-f0mfkj

Conversation

@laazyj

@laazyj laazyj commented Aug 19, 2026

Copy link
Copy Markdown
Owner

What & why

Closes the first item of #341.

packages/examples/cdk.json configured no context at all, so every feature flag was inherited from whatever CDK's unconfigured default happened to be, and synth warned that @aws-cdk/core:defaultCrossStackReferences had never been chosen:

WARNING No cross-stack-reference strength configured, defaulting to "strong".
   ComposureCDK-MultiStackApiStack

The examples are the pattern users copy, so a default left implicit here becomes a default inherited downstream. This sets the flag to "weak" — CDK's recommendedValue for it — and gives the examples one place to declare a flag decision.

What "weak" changes

Cross-stack consumers read the producer's output with Fn::GetStackOutput instead of importing a CloudFormation export. Strong references stop a producer removing an export a consumer still reads — protection worth having for a long-lived system, and the wrong trade for stacks CI deploys and destroys on every run.

Contrary to the flag's own description, this is not confined to cross-region references. The flag docs say "same-region references are always strong (Fn::ImportValue)", but in aws-cdk-lib 2.264.0 the same-account/same-region tail of resolveValue reads:

strength === "strong" ? createImportValue(reference)
                      : (strength === "both" && createImportValue(reference), createGetStackOutput(reference, {}))

So ComposureCDK-MultiStackApiStack's template really does change, and its snapshot moves with it: the producer's output loses its Export, the consumer swaps Fn::ImportValue for Fn::GetStackOutput, and the API deployment's logical-id hash shifts with the body. Nothing else in the suite references across stacks, so that is the only snapshot touched.

No deployed stacks are affected — the examples are torn down after each smoke-test run, so this starts from a clean slate. An existing system migrating from strong would need the staged "both" → deploy everywhere → "weak" path instead, which the README now documents.

Why the context is declared twice

cdk.json for the CLI, and EXAMPLE_CONTEXT in src/app-context.ts for the tests, which build their own App rather than going through the CLI. CDK applies CLI context after an App's context prop, so a divergence would not fail on its own — it would quietly leave the tests asserting a template CI never deploys. A new test asserts the two stay in sync.

Every example now defaults its app parameter to exampleApp() rather than a bare new App(), so a stack synthesised by its own test sees what CI deploys. That is what makes the multi-stack snapshot correct rather than merely updated, and it is where the next flag decision will land without further plumbing.

Tests

test/app-context.test.ts covers:

  • cdk.json's context matches EXAMPLE_CONTEXT
  • exampleApp() applies it, and a caller can override an entry
  • the multi-stack example resolves weakly (Fn::GetStackOutput present, Fn::ImportValue absent)
  • it synthesises without the unconfigured-strength warning — and an app built without the context still emits it, so the test fails if the context ever stops reaching a synthesising app

The warning assertion keys on the annotation id (@aws-cdk/core:crossStackReferencesDefaultStrong) rather than CDK's prose, so a reworded message does not break the build.

Not in this PR

The other two items on #341 — pinning a reviewed flag set generally (81 remain unconfigured) and the multi-phase Stack interaction — are unaddressed. The first is worth its own change following the cdk-floors.json shape: a manifest plus a :check that fails when CDK adds a flag we have not reviewed. Two of the recommended flags collide with decisions already made here, which is the argument for reviewing them individually rather than bulk-enabling: @aws-cdk/core:validateAgainstDefaultRules was deliberately left unset in #339, and @aws-cdk/core:annotationsInValidationReport would route CDK annotations into validation-report.json, which check-validation-report.mjs fails on at any severity.

Checklist

  • Linked to an issue (or it's a small, obvious fix)
  • npm run verify passes locally
  • Tests added/updated for the change
  • If it adds an example stack: registered, listed in the examples README, and covered by a smoke test that exercises its runtime behaviour — n/a, no new stack

Verified beyond verify: the CloudFormation Validate gate from #339 reports no findings on the new Fn::GetStackOutput output, and cdk synth now reports 81 unconfigured flags rather than 82, with the warning gone.


Generated by Claude Code

The examples configured no CDK context at all, so every feature flag was
inherited from whatever CDK's unconfigured default happened to be — and
synth warned that `@aws-cdk/core:defaultCrossStackReferences` had never
been chosen, defaulting to "strong". The examples are the pattern users
copy, so a default left implicit here becomes a default inherited
downstream.

Set the flag to "weak", CDK's recommended value. Cross-stack consumers now
read the producer's output with `Fn::GetStackOutput` instead of importing
a CloudFormation export. Strong references stop a producer removing an
export a consumer still reads — protection worth having for a long-lived
system, and the wrong trade for stacks CI deploys and destroys on every
run.

Contrary to the flag's own description, the choice is not confined to
cross-region references: in aws-cdk-lib 2.264.0 a same-account,
same-region consumer resolves to `Fn::GetStackOutput` under "weak" too, so
`ComposureCDK-MultiStackApiStack`'s template changes and its snapshot moves
with it. The producer's output loses its `Export`; nothing else in the
suite references across stacks.

The context is declared twice by necessity: `cdk.json` for the CLI, and
`EXAMPLE_CONTEXT` for the tests, which build their own `App`. CDK applies
CLI context after `App`'s `context` prop, so a divergence would not fail on
its own — it would leave the tests asserting a template CI never deploys.
A new test asserts the two stay in sync, that the multi-stack example
resolves weakly, and that an app built without the context still warns.

Refs #341
@github-actions

Copy link
Copy Markdown
Contributor

Coverage

Overall line coverage: 99.40% across 24 package(s).

Package Statements Branches Functions Lines
acm 🟢 97.36% 🟢 94.73% 🟢 100.00% 🟢 97.22%
apigateway 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
budgets 🟢 99.20% 🟢 95.55% 🟢 100.00% 🟢 100.00%
cloudformation 🟢 98.57% 🟢 95.20% 🟢 100.00% 🟢 99.46%
cloudfront 🟢 99.40% 🟢 95.14% 🟢 100.00% 🟢 100.00%
cloudwatch 🟢 95.56% 🟡 89.55% 🟢 100.00% 🟢 98.23%
core 🟢 100.00% 🟢 97.43% 🟢 100.00% 🟢 100.00%
custom-resources 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
dynamodb 🟢 100.00% 🟢 93.10% 🟢 100.00% 🟢 100.00%
ec2 🟢 98.81% 🟢 97.72% 🟢 100.00% 🟢 99.58%
eslint-plugin 🟢 90.47% 🟡 83.87% 🟢 100.00% 🟢 98.19%
events 🟢 98.66% 🟢 94.59% 🟢 100.00% 🟢 100.00%
examples 🟢 97.79% 🟡 84.61% 🟢 100.00% 🟢 99.42%
iam 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
kms 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
lambda 🟢 98.00% 🟢 96.82% 🟢 100.00% 🟢 98.41%
logs 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
module-compat 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
neptune 🟢 97.14% 🟡 86.95% 🟢 100.00% 🟢 98.50%
route53 🟢 97.94% 🟢 95.68% 🟢 100.00% 🟢 99.18%
s3 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
ses 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
sns 🟢 100.00% 🟢 100.00% 🟢 100.00% 🟢 100.00%
sqs 🟢 100.00% 🟢 98.63% 🟢 100.00% 🟢 100.00%
Total 🟢 98.18% 🟢 94.81% 🟢 100.00% 🟢 99.40%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants