Review evidence

pulumi/docs PR #21871 3cf8eb5340 generated 2026-09-25T15:18:28Z

Verification trail

#2 ✅ Verified
content/blog/component-state-migrations/index.md:16
The Pulumi documentation page at /docs/iac/guides/building-extending/components/state-migrations/ (titled 'Component state migrations') covers the state…
framing: The claim's title matches the page's title_tag ('Component state migrations'). The frontmatter title is 'State migrations'.; evidence: The page exists at content/docs/iac/guides/building-extending/components/state-migrations.md with title_tag "Component state migrations | Pulumi Docs". Its "Write a migration callback" section sets out the contract: "Return the…; source: repo:content/docs/iac/guides/building-extending/components/state-migrations.md
source: repo:content/docs/iac/guides/building-extending/components/state-migrations.md
framing: exact-match — The claim's title matches the page's title_tag ('Component state migrations'). The frontmatter title is 'State migrations'.
pass1 · url · high confidence
#5 ✅ Verified
content/blog/component-state-migrations/index.md:23
Pulumi components let you turn a group of resources into a reusable building block that can be defined once (e.g., a network, database, or application…
framing: The docs say "logical grouping... reusable building blocks... shared through a library/package... consumed by any team". The claim says "group of resources →…; evidence: The linked components page exists and backs up the claim: "A component is a logical grouping of Pulumi resources that is exposed as a single Pulumi resource" and "Platform teams can use components to codify infrastructure best…; source: repo:content/docs/iac/concepts/components/_index.md L36-51
source: repo:content/docs/iac/concepts/components/_index.md L36-51
framing: exact-match — The docs say "logical grouping... reusable building blocks... shared through a library/package... consumed by any team". The claim says "group of resources → reusable building block shared across projects and teams".
pass1 · url · high confidence
#6 ✅ Verified
content/blog/component-state-migrations/index.md:25
The legacy AWSX VPC component manages the VPC, subnets, route tables, and gateways behind a few lines of code.
framing: Route tables weren't checked separately; subnet.ts and vpcTopology.ts, which handle routing, point the same way.; evidence: The awsx-classic ec2 module includes vpc.ts, natGateway.ts, subnet.ts, and vpcTopology.ts. Its README says "To allow connections from `private` subnets to the internet, NAT gateways will be created... one NAT Gateway will be created for…; source: gh search code --repo pulumi/pulumi-awsx NatGateway path:awsx-classic/ec2
source: gh search code --repo pulumi/pulumi-awsx NatGateway path:awsx-classic/ec2
framing: Route tables weren't checked separately; subnet.ts and vpcTopology.ts, which handle routing, point the same way.
pass1 · feature · medium confidence
#7 ✅ Verified
content/blog/component-state-migrations/index.md:27
Pulumi's component state migrations feature lets component authors ship the upgrade path for a component's saved state alongside the component code itself.
evidence: The feature exists in pulumi/pulumi: PR #24328 (merged), "Execute component state migrations", says "When an existing component is registered with migrations, the engine passes the component's previous state and its child resources…; source: gh pr view 24328 -R pulumi/pulumi; gh search prs --owner pulumi "component state migration"; intuition: The blog post's own notice calls the API experimental. Calling it a "feature" is fine, but readers should see that…
source: gh pr view 24328 -R pulumi/pulumi; gh search prs --owner pulumi "component state migration"
pass1 · feature · medium confidence
#8 ✅ Verified
content/blog/component-state-migrations/index.md:31
The Pulumi state migrations API is experimental and may change.
framing: The SDK comment and the blog callout use the same wording. The docs guide at content/docs/iac/guides/building-extending/components/state-migrations.md says…; evidence: The Node.js SDK source that adds `stateMigrations` (merged in pulumi/pulumi#24715) marks StateMigrationArgs, StateMigrationResult, StateMigration and the `stateMigrations` resource option with the doc comment: "This API is experimental…; source: gh pr diff 24715 -R pulumi/pulumi (sdk/nodejs/resource.ts)
source: gh pr diff 24715 -R pulumi/pulumi (sdk/nodejs/resource.ts)
framing: exact-match — The SDK comment and the blog callout use the same wording. The docs guide at content/docs/iac/guides/building-extending/components/state-migrations.md says the same thing.
pass1 · feature · high confidence
#9 ✅ Verified
content/blog/component-state-migrations/index.md:34
Pulumi hosts a component state migrations discussion at https://github.com/pulumi/pulumi/discussions/24799 for feedback on the feature.
framing: The pre-fetched body was truncated, so only the title confirms the topic. The "for feedback" purpose is how the blog frames it, not something the page was…; evidence: The cited URL returns HTTP 200. Its page title is "Component State Migrations · pulumi pulumi · Discussion #24799 · GitHub", so the discussion exists in the pulumi/pulumi repo on the stated topic.; source: https://github.com/pulumi/pulumi/discussions/24799
source: https://github.com/pulumi/pulumi/discussions/24799
framing: exact-match — The pre-fetched body was truncated, so only the title confirms the topic. The "for feedback" purpose is how the blog frames it, not something the page was seen to say.
pass2 · url · high confidence
#11 ✅ Verified
content/blog/component-state-migrations/index.md:41
The legacy awsx.classic.ec2.Vpc component, in its first version in this example, creates a VPC with one isolated subnet, a route table and its association…
framing: The code comment says "Create an internet gateway if we have public subnets", but the call is unconditional, so the internet gateway is created with only an…; evidence: The example's v1/index.ts creates `new awsx.classic.ec2.Vpc("vpc", {... numberOfNatGateways: 0, subnets: [{ type: "isolated", cidrMask: 24 ...}]})`, so there is one isolated subnet in one AZ. In the classic vpc.ts…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/index.ts; gh api repos/pulumi/pulumi-awsx/contents/awsx-classic/ec2/vpc.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/index.ts; gh api repos/pulumi/pulumi-awsx/contents/awsx-classic/ec2/vpc.ts
framing: The code comment says "Create an internet gateway if we have public subnets", but the call is unconditional, so the internet gateway is created with only an isolated subnet.
pass1 · api-surface · high confidence
#13 ✅ Verified
content/blog/component-state-migrations/index.md:43
Per the AWS CloudFormation documentation, changing an EC2 SecurityGroup's VpcId (i.e., pointing it at a new VPC) requires replacement of the security group.
framing: Source: VpcId "Update requires: Replacement"; claim: changing VpcId requires replacement.; evidence: In the AWS CloudFormation AWS::EC2::SecurityGroup property reference, the VpcId property is described as "The ID of the VPC for the security group." and is listed with "Required: Conditional Type: String Update requires: Replacement".; source: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html
source: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html
framing: exact-match — Source: VpcId "Update requires: Replacement"; claim: changing VpcId requires replacement.
pass3 · attribution · high confidence
#15 ✅ Verified
content/blog/component-state-migrations/index.md:45
In a real application, changes to a component's network can cause downtime or require more resource replacements.
evidence: This is a hedged, hypothetical statement ("can cause") about a database the example doesn't create. The surrounding text backs the replacement cascade: the security group's VpcId forces replacement when the VPC changes (line 43, which…; source: repo:content/blog/component-state-migrations/index.md L43-45 (context only); https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html#cfn-ec2-securitygroup-vpcid (cited on L43); intuition: A hedged hypothetical that's close to not-a-claim; there's little here to falsify.
source: repo:content/blog/component-state-migrations/index.md L43-45 (context only); https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html#cfn-ec2-securitygroup-vpcid (cited on L43)
pass1 · behavior · low confidence
#16 ✅ Verified
content/blog/component-state-migrations/index.md:45
If a database has to be recreated, its replacement does not automatically contain the old data.
framing: No Pulumi page says outright that data is lost. The claim is inferred from the documented delete-then-create behavior plus general knowledge that a new…; evidence: (re-verified after own-file-only) A separate Pulumi doc describes replacement as deleting the old resource and creating a new one: "By default, when we run `pulumi up`, we see that the old resource is deleted and the new one created." A…; source: repo:content/docs/iac/concepts/resources/options/aliases.md L24
source: repo:content/docs/iac/concepts/resources/options/aliases.md L24
framing: No Pulumi page says outright that data is lost. The claim is inferred from the documented delete-then-create behavior plus general knowledge that a new database starts empty.
pass1 · behavior · medium confidence
#17 ✅ Verified
content/blog/component-state-migrations/index.md:45
The AWSX VPC example described in this post does not create a database.
framing: I only read v1 directly. The empty "rds" search suggests v2 and v3 don't create a database either, but I didn't open their files.; evidence: The example's v1/index.ts (base64-decoded) creates only an `awsx.classic.ec2.Vpc` and an `aws.ec2.SecurityGroup("database", { description: "Database resources that must keep using the existing VPC", vpcId: vpc.id ... })`. It has no RDS…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/index.ts; gh search code --repo pulumi/examples rds path:aws-ts-awsx-vpc-state-migration
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/index.ts; gh search code --repo pulumi/examples rds path:aws-ts-awsx-vpc-state-migration
framing: I only read v1 directly. The empty "rds" search suggests v2 and v3 don't create a database either, but I didn't open their files.
pass1 · feature · medium confidence
#18 ✅ Verified
content/blog/component-state-migrations/index.md:47
The modern awsx.ec2.Vpc component, in the second version of the example, replaces the legacy component while keeping the existing network.
framing: The claim describes the linked example's v2 code, and that code uses an alias plus a state migration from the classic VPC type to the modern awsx.ec2.Vpc.; evidence: The v2 program in pulumi/examples decodes to `new awsx.ec2.Vpc("vpc", {...}, { aliases: [{ type: classicVpcType }], stateMigrations: [migrateClassicVpc] })`, and its security group is described as "Database resources that must keep using…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/index.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/index.ts
framing: exact-match — The claim describes the linked example's v2 code, and that code uses an alias plus a state migration from the classic VPC type to the modern awsx.ec2.Vpc.
pass1 · behavior · high confidence
#19 ✅ Verified
content/blog/component-state-migrations/index.md:49
In the third version of the example, Pulumi still manages the resources, but the user's code controls each resource instead of relying on the component to…
evidence: This sentence describes how the author's own example is built. The example's v3 package.json lists only "@pulumi/aws": "7.44.0" and "@pulumi/pulumi" as dependencies, with no @pulumi/awsx. That fits the claim that v3 drops the AWSX…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/package.json
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/package.json
pass1 · behavior · medium confidence
#20 ✅ Verified
content/blog/component-state-migrations/index.md:51
Across all three versions of the AWSX VPC example (v1, v2, v3), the underlying AWS resource IDs stay the same.
framing: The README states preserved physical resources and retained IDs. That supports the claim that the AWS resource IDs stay the same across v1, v2 and v3. I…; evidence: The pulumi/examples README says the example will "Migrate an existing VPC from classic AWSX to modern AWSX, then to plain AWS resources, while preserving its physical resources." It also says each migration's `newState` is "the complete…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md
framing: entailed-narrower — The README states preserved physical resources and retained IDs. That supports the claim that the AWS resource IDs stay the same across v1, v2 and v3. I didn't run the example to confirm this at runtime.
pass1 · behavior · medium confidence
#21 ✅ Verified
content/blog/component-state-migrations/index.md:53
In the AWSX VPC example's resource trees, awsx: entries are component records and aws: entries represent the AWS resources that stay in place.
framing: The claim is mostly the legend for the author's own tree diagram. The only checkable part is that awsx types are components and aws types are provider…; evidence: The trees at L55-77 fit the legend: `awsx:x:ec2:Vpc`, `awsx:x:ec2:Subnet`, `awsx:x:ec2:InternetGateway` (legacy) and `awsx:ec2:Vpc` (modern) are AWSX component types wrapping `aws:ec2/...` managed resources (VPC, subnet, route table…; source: repo:content/blog/component-state-migrations/index.md L51-77; gh search code --repo pulumi/pulumi-awsx awsx:x:ec2:Vpc (HTTP 429)
source: repo:content/blog/component-state-migrations/index.md L51-77; gh search code --repo pulumi/pulumi-awsx awsx:x:ec2:Vpc (HTTP 429)
framing: The claim is mostly the legend for the author's own tree diagram. The only checkable part is that awsx types are components and aws types are provider resources, which matches how AWSX is built (a component library over the AWS provider).
pass1 · api-surface · medium confidence
#22 ✅ Verified
content/blog/component-state-migrations/index.md:55
In v1 of the AWSX VPC example, the resource tree consists of an `awsx:x:ec2:Vpc` component containing an `aws:ec2/vpc:Vpc`, an `awsx:x:ec2:Subnet` component…
framing: The blog's tree is identical to the tree in the linked example's README.; evidence: The example's README shows the same v1 tree: "v1: awsx:x:ec2:Vpc \"vpc\" ├── aws:ec2/vpc:Vpc \"vpc\" ├── awsx:x:ec2:Subnet \"vpc-isolated-0\" … └── awsx:x:ec2:InternetGateway \"vpc\" └── aws:ec2/internetGateway:InternetGateway \"vpc\"".…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md; pulumi/pulumi-awsx:awsx-classic/ec2/internetGateway.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md; pulumi/pulumi-awsx:awsx-classic/ec2/internetGateway.ts
framing: exact-match — The blog's tree is identical to the tree in the linked example's README.
pass1 · api-surface · high confidence
#23 ✅ Verified
content/blog/component-state-migrations/index.md:65
In v2 of the example, the resource tree under awsx:ec2:Vpc "vpc" contains aws:ec2/vpc:Vpc "vpc", which in turn contains aws:ec2/subnet:Subnet…
evidence: The example's v2 migration code builds the same parent chain: `newVpc = rename(oldVpc, newVpcUrn, newRootUrn)`, `newSubnet = rename(oldSubnet, newSubnetUrn, newVpcUrn)`, `newRouteTable = rename(..., newSubnetUrn)`…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
pass1 · api-surface · high confidence
#24 ✅ Verified
content/blog/component-state-migrations/index.md:72
In v3 of the example, the resource tree under aws:ec2/vpc:Vpc "vpc" contains aws:ec2/subnet:Subnet "vpc-isolated-1" (with a nested…
framing: The claim says the route table and association are both nested under the subnet. In the code, the association is nested one level further, under the route…; evidence: The v3 example code has the same structure. It declares `new aws.ec2.Vpc("vpc", ...)` with no wrapping component. It then creates Subnet "vpc-isolated-1" with `{ parent: vpc }`, RouteTable "vpc-isolated-1" with `{ parent: isolatedSubnet…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
framing: exact-match — The claim says the route table and association are both nested under the subnet. In the code, the association is nested one level further, under the route table. The blog's tree shows that correctly.
pass1 · api-surface · high confidence
#25 ✅ Verified
content/blog/component-state-migrations/index.md:81
In Pulumi's state, each record (both physical resources and the components that group them) has a Pulumi name called a URN.
framing: Only the attribution to "Pulumi's" state is sourced, and it is a well-established concept. The implementer's guide covers both custom and component resources…; evidence: Pulumi's developer docs say "Each resource registered with the Pulumi engine is logically identified by its uniform resource name (URN)." They also say that, besides its URN, a component resource has inputs, outputs, and children, so…; source: https://pulumi-developer-docs.readthedocs.io/latest/developer-docs/providers/implementers-guide.html
source: https://pulumi-developer-docs.readthedocs.io/latest/developer-docs/providers/implementers-guide.html
framing: exact-match — Only the attribution to "Pulumi's" state is sourced, and it is a well-established concept. The implementer's guide covers both custom and component resources having URNs.
pass3 · api-surface · high confidence
#26 ✅ Verified
content/blog/component-state-migrations/index.md:83
The legacy AWSX VPC component wraps the subnet and internet gateway resources in separate child components, while modern AWSX removes those wrapper…
framing: I didn't read the modern parent assignments (for example, subnet parented to the VPC resource) line by line. The search results only confirm that the…; evidence: In pulumi-awsx source, the classic subnet is its own component (`super("awsx:x:ec2:Subnet", name, {}, { parent: vpc, ...opts })` in awsx-classic/ec2/subnet.ts), and a separate awsx-classic/ec2/internetGateway.ts creates the…; source: gh search code --repo pulumi/pulumi-awsx "awsx:x:ec2:Subnet"; gh search code --repo pulumi/pulumi-awsx "new aws.ec2.InternetGateway"
source: gh search code --repo pulumi/pulumi-awsx "awsx:x:ec2:Subnet"; gh search code --repo pulumi/pulumi-awsx "new aws.ec2.InternetGateway"
framing: I didn't read the modern parent assignments (for example, subnet parented to the VPC resource) line by line. The search results only confirm that the wrappers are gone.
pass1 · behavior · medium confidence
#27 ✅ Verified
content/blog/component-state-migrations/index.md:83
Modern AWSX removes the wrapper components used by legacy AWSX and puts the managed resources under different parents.
evidence: In modern pulumi-awsx `awsx/ec2/vpc.ts`, plain aws resources are created directly, with no Subnet or InternetGateway wrapper components. The IGW and subnets use `{ parent: vpc, dependsOn: [vpc] }`, route tables use `{ parent: subnet, ...…; source: gh api repos/pulumi/pulumi-awsx/contents/awsx/ec2/vpc.ts
source: gh api repos/pulumi/pulumi-awsx/contents/awsx/ec2/vpc.ts
pass1 · behavior · high confidence
#28 ✅ Verified
content/blog/component-state-migrations/index.md:83
In this example, the Pulumi name of the subnet changes from vpc-isolated-0 to vpc-isolated-1 when moving from legacy to modern AWSX.
framing: Example source code uses classicSubnetName "vpc-isolated-0" → modernSubnetName "vpc-isolated-1", same as the claim.; evidence: The linked example's v2 migration defines `const classicSubnetName = "vpc-isolated-0";` and `const modernSubnetName = "vpc-isolated-1";`. Its migration.spec.ts files map the old URN "vpc-isolated-0" (legacy awsx:x:ec2:Subnet wrapper) to…; source: gh search code --repo pulumi/examples "vpc-isolated-0" / "vpc-isolated-1" (aws-ts-awsx-vpc-state-migration/v2/migration.ts, v2/migration.spec.ts)
source: gh search code --repo pulumi/examples "vpc-isolated-0" / "vpc-isolated-1" (aws-ts-awsx-vpc-state-migration/v2/migration.ts, v2/migration.spec.ts)
framing: exact-match — Example source code uses classicSubnetName "vpc-isolated-0" → modernSubnetName "vpc-isolated-1", same as the claim.
pass1 · behavior · high confidence
#29 ✅ Verified
content/blog/component-state-migrations/index.md:85
The upgrade from legacy to modern AWSX needs to remove component wrappers and transfer references to the resources that take their place.
framing: The aliases link belongs to the sentence before this one. This claim describes the example migration, and the example's source code confirms it.; evidence: The example's v2 migration.ts drops the classic `awsx:x:ec2:Subnet` and `awsx:x:ec2:InternetGateway` wrapper components from `newState` and maps their URNs to the replacement resources in `successors`, with the comment "The engine uses…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts; repo:content/docs/iac/concepts/resources/options/aliases.md
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts; repo:content/docs/iac/concepts/resources/options/aliases.md
framing: exact-match — The aliases link belongs to the sentence before this one. This claim describes the example migration, and the example's source code confirms it.
pass1 · url · high confidence
#30 ✅ Verified
content/blog/component-state-migrations/index.md:89
To migrate an existing network to modern AWSX, you register the new VPC component with an alias for the legacy component type and a migration callback via…
framing: This file confirms the legacy type constant and the pulumi.StateMigration callback. The alias and `stateMigrations` option wiring are not visible in the…; evidence: The cited example defines the legacy type used for aliasing and the migration callback: `export const classicVpcType = "awsx:x:ec2:Vpc"; export const modernVpcType = "awsx:ec2:Vpc";` and `export const migrateClassicVpc…; source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: entailed-narrower — This file confirms the legacy type constant and the pulumi.StateMigration callback. The alias and `stateMigrations` option wiring are not visible in the fetched (truncated) excerpt.
pass2 · api-surface · medium confidence
#31 ✅ Verified
content/blog/component-state-migrations/index.md:89
The `migrateClassicVpc` migration callback function used in the example comes from the example repository's migration.ts file at…
evidence: The cited file loads (HTTP 200) and exports the callback the claim names: "export const migrateClassicVpc: pulumi.StateMigration = (args) => {".; source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: exact-match
pass2 · cross-reference · high confidence
#32 ✅ Verified
content/blog/component-state-migrations/index.md:95
A Pulumi component state migration callback returns `newState`, the complete set of records that should replace the old component and its children, and…
framing: In the example, successors lists every old URN, including ones only renamed. Those URNs still go away, so this fits the claim's wording "each old URN that…; evidence: The official pulumi/examples migration (typed `pulumi.StateMigration`) returns `{ newState: [newRoot, newVpc, ...], successors: Object.fromEntries(urnMap) }`, where urnMap maps each old URN to its replacement, with the comment "The…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: In the example, successors lists every old URN, including ones only renamed. Those URNs still go away, so this fits the claim's wording "each old URN that disappears".
pass1 · api-surface · medium confidence
#33 ✅ Verified
content/blog/component-state-migrations/index.md:104
The full migration code for this example is available at https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts.
evidence: The cited URL returns HTTP 200. It contains the migration code for an awsx classic-to-modern VPC state migration: "export const migrateClassicVpc: pulumi.StateMigration = (args) => {", along with helpers that rename the child resource URNs.; source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: exact-match
pass2 · url · high confidence
#34 ✅ Verified
content/blog/component-state-migrations/index.md:106
In the example migration callback, the first checks make the callback safe to run again: if the state already uses modern AWSX or plain AWS resources, there…
framing: The claim describes the linked full migration code. The embedded snippet file (migration-sketch.ts.txt) was not found under static/programs, so I checked the…; evidence: In the example's migration.ts, `migrateClassicVpc` begins with `if (oldRoot.type === modernVpcType || oldRoot.type === awsVpcType) { return undefined; }`, then `if (oldRoot.type !== classicVpcType) { throw new Error(...) }`. That is the…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: exact-match — The claim describes the linked full migration code. The embedded snippet file (migration-sketch.ts.txt) was not found under static/programs, so I checked the upstream source instead.
pass1 · behavior · high confidence
#35 ✅ Verified
content/blog/component-state-migrations/index.md:106
In the example's migration callback, an unexpected component type raises an error instead of attempting to guess how to migrate it.
framing: The blog links to this file as the "Full migration code". I couldn't find the local snippet file (migration-sketch.ts.txt), so I only checked the full code…; evidence: The linked example's migration callback returns early for modern AWSX or plain AWS root types. For any other type it throws: `if (oldRoot.type !== classicVpcType) { throw new Error(`expected a ${classicVpcType} root, found ...`) }`.; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: exact-match — The blog links to this file as the "Full migration code". I couldn't find the local snippet file (migration-sketch.ts.txt), so I only checked the full code in the upstream repo.
pass1 · behavior · high confidence
#36 ✅ Verified
content/blog/component-state-migrations/index.md:108
The example's `rename` helper function copies the saved record and changes its URN, type, and parent while preserving the AWS resource ID and other saved…
framing: The blog snippet file static/programs/awsx-vpc-state-migration-blog/migration-sketch.ts.txt was not found at that path, so this was checked against the…; evidence: The example's migration.ts defines `rename`, which deep-copies the record (`JSON.parse(JSON.stringify(resource))`) and then sets only `renamed.urn = urn`, `renamed.type = typeFromUrn(urn)` and `renamed.parent`. Every other field…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: exact-match — The blog snippet file static/programs/awsx-vpc-state-migration-blog/migration-sketch.ts.txt was not found at that path, so this was checked against the upstream migration.ts that the post links to.
pass1 · api-surface · high confidence
#37 ✅ Verified
content/blog/component-state-migrations/index.md:110
The two subnet entries in the migration's `successors` map let the Pulumi engine know that the old component wrapper and the managed subnet point to the same…
evidence: In the published example migration, both the old subnet component URN and the old managed subnet URN map to the same new subnet URN: `[oldSubnetComponentUrn, newSubnetUrn], [resourceUrn(oldSubnet), newSubnetUrn]`. The code's own comment…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts; repo:static/programs/awsx-vpc-state-migration-blog-typescript/migration-sketch.ts.txt
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts; repo:static/programs/awsx-vpc-state-migration-blog-typescript/migration-sketch.ts.txt
pass1 · behavior · medium confidence
#38 ✅ Verified
content/blog/component-state-migrations/index.md:110
The VPC successor mapping keeps the security group's reference connected to the migrated VPC record, which retains the same AWS VPC ID.
framing: I checked this against the example code, not the engine's own implementation. That the engine rewrites the security group's reference comes from the…; evidence: In the example migration, `successors` includes `[resourceUrn(oldVpc), newVpcUrn]`, and the code comment says "The engine uses successors to rewrite references to renamed and folded resources." `rename` deep-copies the old record and…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v2/migration.ts
framing: I checked this against the example code, not the engine's own implementation. That the engine rewrites the security group's reference comes from the example's code comment.
pass1 · behavior · medium confidence
#39 ✅ Verified
content/blog/component-state-migrations/index.md:114
The third version of the example declares the VPC, subnet, route table, association, and internet gateway directly with `@pulumi/aws`.
evidence: v3/index.ts in pulumi/examples has `import * as aws from "@pulumi/aws"` and declares `new aws.ec2.Vpc("vpc"...)`, `aws.ec2.Subnet`, `aws.ec2.RouteTable`, `aws.ec2.RouteTableAssociation`, and `aws.ec2.InternetGateway` directly. It has no…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
framing: exact-match
pass1 · api-surface · high confidence
#41 ✅ Verified
content/blog/component-state-migrations/index.md:116
The second migration, available at github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v3/migration.ts, removes the AWSX VPC component…
framing: The source was truncated, but the part that was fetched shows the root being collapsed and the VPC being renamed to args.urn under the old root's parent.…; evidence: The file defines `migrateAwsxVpc`. It maps the AWSX component root to the new URN (`[oldRootUrn, newVpcUrn], [oldVpcUrn, newVpcUrn]`) and moves the child VPC into the root's position (`const newVpc = rename(oldVpc, newVpcUrn, parent);`…; source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v3/migration.ts
source: https://github.com/pulumi/examples/blob/master/aws-ts-awsx-vpc-state-migration/v3/migration.ts
framing: exact-match — The source was truncated, but the part that was fetched shows the root being collapsed and the VPC being renamed to args.urn under the old root's parent. Calling it the "second" migration fits: the file also imports the classic migration.
pass2 · url · high confidence
#42 ✅ Verified
content/blog/component-state-migrations/index.md:118
The VPC registration in the third version of the example keeps aliases for both previous component types and both migration callbacks.
framing: I did not open the contents of `vpcStateMigrations` in the upstream repo. The two callbacks are confirmed by the blog's snippet and by migration.spec.ts…; evidence: The claim holds. In pulumi/examples v3/migration.ts, the VPC's aliases are defined as `export const vpcMigrationAliases = [{ type: classicVpcType }, { type: modernVpcType }];`, and v3/index.ts passes both `aliases: vpcMigrationAliases`…; source: gh search code --owner pulumi vpcMigrationAliases; gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts; repo:static/programs/awsx-vpc-state-migration-blog-typescript/plain-vpc.ts.txt
source: gh search code --owner pulumi vpcMigrationAliases; gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts; repo:static/programs/awsx-vpc-state-migration-blog-typescript/plain-vpc.ts.txt
framing: exact-match — I did not open the contents of `vpcStateMigrations` in the upstream repo. The two callbacks are confirmed by the blog's snippet and by migration.spec.ts importing both.
pass1 · api-surface · high confidence
#43 ✅ Verified
content/blog/component-state-migrations/index.md:124
Pulumi runs multiple registered migration callbacks in order, passing each callback's result to the next callback.
evidence: The engine source matches the claim. It says runStateMigrationCallbacks "evaluates an ordered callback chain", and applyStateMigrations serializes the prior subtree to "hand it to each migration in turn". So the callbacks run one after…; source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration.go; gh search code --repo pulumi/pulumi runStateMigrationCallbacks (pkg/resource/deploy/state_migration_callback.go)
source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration.go; gh search code --repo pulumi/pulumi runStateMigrationCallbacks (pkg/resource/deploy/state_migration_callback.go)
pass1 · behavior · high confidence
#44 ✅ Verified
content/blog/component-state-migrations/index.md:124
In the example, once both migrations have run, both migration callbacks return no result on later updates.
evidence: I checked the example code. After both migrations the saved root is an `aws:ec2/vpc:Vpc`, and both callbacks return undefined for that case. `migrateClassicVpc` has `if (oldRoot.type === modernVpcType || oldRoot.type === awsVpcType) {…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/migration.ts and v3/classic-migration.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/migration.ts and v3/classic-migration.ts
pass1 · behavior · high confidence
#45 ✅ Verified
content/blog/component-state-migrations/index.md:124
A stack still using legacy AWSX can upgrade directly to the plain AWS version using these chained migrations.
framing: The README's "direct upgrade" from v1 matches the claim that a stack on legacy AWSX "can upgrade directly to the plain AWS version".; evidence: The v3 README in the linked pulumi/examples project says: "Both historical aliases and migration callbacks are retained, allowing upgrades from either v1 or v2". It also says "Deploy v2 (or v1 for a direct upgrade) first". In…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/README.md; repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/README.md; repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v3/index.ts
framing: exact-match — The README's "direct upgrade" from v1 matches the claim that a stack on legacy AWSX "can upgrade directly to the plain AWS version".
pass1 · feature · high confidence
#46 ✅ Verified
content/blog/component-state-migrations/index.md:126
Keeping earlier state migrations attached to a component means its users can skip versions without having to edit stack state by hand.
framing: "Skip versions without editing state by hand" is my reading of how chained, idempotent callbacks work. The source doesn't say it in those words.; evidence: The engine source shows migrations are chained and meant to stay attached. It serializes the prior subtree "and hand[s] it to each migration in turn", and a comment says no-op migrations return early "so permanently attached migrations…; source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration.go
source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration.go
framing: "Skip versions without editing state by hand" is my reading of how chained, idempotent callbacks work. The source doesn't say it in those words.
pass1 · feature · medium confidence
#47 ✅ Verified
content/blog/component-state-migrations/index.md:130
In the AWSX VPC example, keeping resource IDs stable across a migration does not guarantee an empty preview, since the example can still show in-place…
framing: The README ties the in-place updates to upgrades from classic AWSX. The blog says "this example can still show" them, which is a hedged, consistent version…; evidence: The example's README (both v2 and v3) says the resources "should be retained, with no creates, deletes, or replacements. An upgrade from classic AWSX can include in-place updates for provider defaults and tags."; source: gh search code --repo pulumi/examples "in-place" path:aws-ts-awsx-vpc-state-migration (v2/README.md, v3/README.md)
source: gh search code --repo pulumi/examples "in-place" path:aws-ts-awsx-vpc-state-migration (v2/README.md, v3/README.md)
framing: entailed-narrower — The README ties the in-place updates to upgrades from classic AWSX. The blog says "this example can still show" them, which is a hedged, consistent version of that.
pass1 · behavior · high confidence
#48 ✅ Verified
content/blog/component-state-migrations/index.md:132
To try the AWSX VPC example, you start with v1 and follow its README, using the same stack, backend, project name, AWS region, and availability zone for each…
framing: The blog lists stack, backend, project name, region, and AZ. The README list also includes the shell, so the blog's list is a subset of what the README…; evidence: The example's README says to run the stages "against the **same stack and backend**". The v1 README says to continue to v2 or v3 while "keeping the same shell, backend, project name, region, availability zone, and stack."; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/README.md (and ../README.md)
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/v1/README.md (and ../README.md)
framing: entailed-narrower — The blog lists stack, backend, project name, region, and AZ. The README list also includes the shell, so the blog's list is a subset of what the README requires.
pass1 · behavior · high confidence
#49 ✅ Verified
content/blog/component-state-migrations/index.md:134
Before each upgrade in the AWSX VPC example, running `pulumi preview` should show no creates, deletes, or replacements for the existing VPC, subnet, route…
framing: The README says physical resources are preserved and IDs are kept; the blog's expected preview (no creates, deletes or replacements, possibly some in-place…; evidence: The pulumi/examples README for aws-ts-awsx-vpc-state-migration says the example migrates the VPC "while preserving its physical resources". It lists the same six resources: "one isolated subnet, a route table and association, an internet…; source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md
source: gh api repos/pulumi/examples/contents/aws-ts-awsx-vpc-state-migration/README.md
framing: entailed-narrower — The README says physical resources are preserved and IDs are kept; the blog's expected preview (no creates, deletes or replacements, possibly some in-place updates) follows from that.
pass1 · behavior · medium confidence
#50 ✅ Verified
content/blog/component-state-migrations/index.md:134
Pulumi's `pulumi preview` command evaluates a component state migration without saving it, while `pulumi up` saves the migrated state.
framing: Engine code: previewActions.OnStateMigration does not persist; updateActions.OnStateMigration calls manager.StateMigration.; evidence: The claim is correct. In pkg/engine/update.go, the update path's `OnStateMigration` calls `manager.StateMigration(transaction)` to persist the migration and reports "State migration applied". The preview path's `OnStateMigration` only…; source: gh pr diff 24713 -R pulumi/pulumi (pkg/engine/update.go); repo:content/docs/iac/guides/building-extending/components/state-migrations.md L153
source: gh pr diff 24713 -R pulumi/pulumi (pkg/engine/update.go); repo:content/docs/iac/guides/building-extending/components/state-migrations.md L153
framing: exact-match — Engine code: previewActions.OnStateMigration does not persist; updateActions.OnStateMigration calls manager.StateMigration.
pass1 · behavior · high confidence
#51 ✅ Verified
content/blog/component-state-migrations/index.md:138
When users upgrade a component with a registered state migration and run Pulumi, Pulumi runs the migration as part of the normal preview and update.
framing: The engine PR says "normal updates" but never mentions preview. Only the docs guide covers preview, and in the engine a preview is a dry-run update, so that…; evidence: Engine PR pulumi/pulumi#24328 (merged) says: "When an existing component is registered with migrations, the engine passes the component's previous state and its child resources through the migration callbacks before planning any…; source: gh pr view 24328 -R pulumi/pulumi; repo:content/docs/iac/guides/building-extending/components/state-migrations.md L145-155
source: gh pr view 24328 -R pulumi/pulumi; repo:content/docs/iac/guides/building-extending/components/state-migrations.md L145-155
framing: The engine PR says "normal updates" but never mentions preview. Only the docs guide covers preview, and in the engine a preview is a dry-run update, so that part is corroborated rather than directly confirmed.
pass1 · behavior · medium confidence
#52 ✅ Verified
content/blog/component-state-migrations/index.md:138
When a component author registers a state migration inside a component's implementation, users of that component do not need to write the migration, attach…
framing: The part about users not writing the migration or attaching the callback follows from how the option is designed (the author sets it in the constructor). I…; evidence: The SDK has a `StateMigrations` resource option (sdk/go/pulumi/resource.go), and the engine applies it when the resource is registered (pkg/resource/deploy/source_eval.go). That means a component constructor can attach the migration…; source: gh search code --owner pulumi stateMigrations (pulumi/pulumi sdk/go/pulumi/resource.go, pkg/resource/deploy/source_eval.go); repo:content/docs/iac/guides/building-extending/components/state-migrations.md L24, L113
source: gh search code --owner pulumi stateMigrations (pulumi/pulumi sdk/go/pulumi/resource.go, pkg/resource/deploy/source_eval.go); repo:content/docs/iac/guides/building-extending/components/state-migrations.md L24, L113
framing: The part about users not writing the migration or attaching the callback follows from how the option is designed (the author sets it in the constructor). I didn't trace the full engine code path, so confidence is medium.
pass1 · feature · medium confidence
#53 ✅ Verified
content/blog/component-state-migrations/index.md:140
For an internal component change that keeps the same component inputs and outputs, users can keep their existing component calls without needing to know…
framing: The claim that callers can leave their code unchanged follows from how the feature is designed: the migration is registered inside the component. No source…; evidence: pulumi/pulumi#24715 (merged) says: "State migrations let components evolve their internal resource structure while preserving existing infrastructure. Callbacks transform the recorded state of a resource and its descendants before the…; source: gh pr view 24715 -R pulumi/pulumi; gh pr list -R pulumi/pulumi --search "state migrations"
source: gh pr view 24715 -R pulumi/pulumi; gh pr list -R pulumi/pulumi --search "state migrations"
framing: The claim that callers can leave their code unchanged follows from how the feature is designed: the migration is registered inside the component. No source says it word for word.
pass1 · behavior · medium confidence
#56 ✅ Verified
content/docs/iac/concepts/resources/options/statemigrations.md:75
State migration callbacks return no result when the state no longer needs migration.
framing: SDK: a result is returned "when it changes the state", nil means "unchanged", and callbacks must be idempotent. Together these give the doc's rule "return no…; evidence: The Go SDK says a result is returned only when the callback changes state, and that a nil result means no change. Quotes: "StateMigrationResult is returned by a state migration callback when it changes the state." and "Returning a nil…; source: gh api repos/pulumi/pulumi/contents/sdk/go/pulumi/state_migration.go
source: gh api repos/pulumi/pulumi/contents/sdk/go/pulumi/state_migration.go
framing: entailed-narrower — SDK: a result is returned "when it changes the state", nil means "unchanged", and callbacks must be idempotent. Together these give the doc's rule "return no result when the state no longer needs migration".
pass1 · behavior · high confidence
#57 ✅ Verified
content/docs/iac/guides/building-extending/components/state-migrations.md:39
In a component state migration's successor mappings, each mapping connects an old URN omitted from the result to the URN of the returned resource that takes…
framing: The source maps each old URN missing from the result to its successor URN in the result, which is the same thing the claim says.; evidence: The engine source matches the claim. It defines `SuccessorURNs` as a map that "maps every URN present in PriorSubtree but absent from ResultSubtree directly to its final successor URN in ResultSubtree". Its validation also rejects a…; source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration_models.go (from merged pulumi/pulumi#24328)
source: gh api repos/pulumi/pulumi/contents/pkg/resource/deploy/state_migration_models.go (from merged pulumi/pulumi#24328)
framing: exact-match — The source maps each old URN missing from the result to its successor URN in the result, which is the same thing the claim says.
pass1 · behavior · high confidence
#58 ✅ Verified
content/docs/iac/guides/building-extending/components/state-migrations.md:41
The checkpoint resource format includes fields such as `urn`, `type`, `id`, `parent`, `provider`, `inputs`, and `outputs`.
evidence: The checkpoint resource format is the `ResourceV3` struct in pulumi/pulumi `sdk/go/common/apitype/core.go`; code search found `type ResourceV3 struct {`. As far as I know, that struct has JSON fields `urn`, `type`, `id`, `parent`…; source: gh search code --repo pulumi/pulumi "type ResourceV3 struct" → sdk/go/common/apitype/core.go
source: gh search code --repo pulumi/pulumi "type ResourceV3 struct" → sdk/go/common/apitype/core.go
pass1 · api-surface · medium confidence
#60 ✅ Verified
content/docs/iac/guides/building-extending/components/state-migrations.md:41
State entries in a component state migration use the checkpoint resource format described at https://pulumi-developer-docs.readthedocs.io/latest/docs/reference…
framing: The link points to the generated deployment-schema reference in pulumi/pulumi; the specific anchor and the callback's use of the format were not directly…; evidence: The linked target exists: `gh api repos/pulumi/pulumi/contents/docs/references` lists `deployment-schema.md`, the source of the readthedocs developer-docs page. The fields named on L41 (`urn`, `type`, `id`, `parent`, `provider`…; source: gh api repos/pulumi/pulumi/contents/docs/references (deployment-schema.md present)
source: gh api repos/pulumi/pulumi/contents/docs/references (deployment-schema.md present)
framing: entailed-narrower — The link points to the generated deployment-schema reference in pulumi/pulumi; the specific anchor and the callback's use of the format were not directly confirmed.
pass1 · cross-reference · medium confidence
#61 ✅ Verified
content/docs/iac/guides/building-extending/components/state-migrations.md:205
A state migration callback that returns no result can remain attached when using update plans or targeted updates.
framing: The source covers partial updates, plan use and pending-state recovery. The claim names only update plans and targeted updates, which are a subset of those…; evidence: The engine architecture doc lists the targeted-update and saved-plan restrictions, then says: "These restrictions apply only when a callback changes state. A permanently attached callback can return `None` without blocking partial…; source: gh api repos/pulumi/pulumi/contents/docs/architecture/deployment-execution/state-migrations.md
source: gh api repos/pulumi/pulumi/contents/docs/architecture/deployment-execution/state-migrations.md
framing: entailed-narrower — The source covers partial updates, plan use and pending-state recovery. The claim names only update plans and targeted updates, which are a subset of those cases.
pass1 · behavior · high confidence
#62 ✅ Verified
content/docs/iac/guides/building-extending/components/state-migrations.md:205
The restrictions on state-changing migration results do not require removing an already-applied state migration callback.
framing: PR says 'No-op migrations are ignored'; the claim applies this to already-applied callbacks, which are no-ops if written as the doc (L50) advises.; evidence: The engine PR that added migration execution says: "No-op migrations are ignored, and state-changing migrations are rejected when they cannot be applied safely." The docs tell authors to write callbacks that return no result once state…; source: gh pr view 24328 -R pulumi/pulumi (Execute component state migrations)
source: gh pr view 24328 -R pulumi/pulumi (Execute component state migrations)
framing: entailed-narrower — PR says 'No-op migrations are ignored'; the claim applies this to already-applied callbacks, which are no-ops if written as the doc (L50) advises.
pass1 · behavior · medium confidence
#59 🤝 Matches
content/docs/iac/guides/building-extending/components/state-migrations.md:41
The Pulumi option reference at /docs/iac/concepts/resources/options/statemigrations/#callback-api explains the state migration callback API.
evidence: The target page exists and has a "## Callback API" heading (anchor #callback-api) that describes the callback API: "Each migration callback is a pure function that transforms the saved state of a component and its children into the state…; source: repo:content/docs/iac/concepts/resources/options/statemigrations.md L25-33
source: repo:content/docs/iac/concepts/resources/options/statemigrations.md L25-33
framing: exact-match
pass1 · cross-reference · high confidence
#1 ➖ Not a claim
content/blog/component-state-migrations/index.md:3
date: 2026-09-25
evidence: This is the `date:` field in the blog post's front matter. It sets the post's own publication date, so it's metadata the author chooses, not a checkable fact about the world. It also matches today's date (2026-09-25).; source: content/blog/component-state-migrations/index.md:L3 (front matter)
source: content/blog/component-state-migrations/index.md:L3 (front matter)
pass3 · numerical · high confidence
#3 ➖ Not a claim
content/blog/component-state-migrations/index.md:17
text: Component state migrations
framing: This is a title or topic label, not an assertion. The source hint "Component" is a false positive from the regex extractor.; evidence: The text "Component state migrations" is a title or heading phrase that matches the blog post's slug. It doesn't say anything true or false and isn't attributed to any third-party source, so there's nothing to verify. The regex flagged…; source: content/blog/component-state-migrations/index.md:L17 (claim text itself)
source: content/blog/component-state-migrations/index.md:L17 (claim text itself)
framing: This is a title or topic label, not an assertion. The source hint "Component" is a false positive from the regex extractor.
pass3 · attribution · high confidence
#12 ➖ Not a claim
content/blog/component-state-migrations/index.md:41
In this example, a security group sits outside the awsx.classic.ec2.Vpc component and refers to the VPC.
evidence: The sentence describes how the author's own blog example is set up: a security group defined outside the component that refers to the VPC. There is no third-party assertion to check. The name awsx.classic.ec2.Vpc belongs to Pulumi's…; source: content/blog/component-state-migrations/index.md L41 (author's own example description)
source: content/blog/component-state-migrations/index.md L41 (author's own example description)
pass3 · entity-spec · medium confidence
#40 ➖ Not a claim
content/blog/component-state-migrations/index.md:114
This second migration changes who defines the resources in the program, and the configuration can then be adjusted in a separate update.
evidence: L114 describes how the blog's own example is set up and the workflow it recommends: "This migration changes who defines those resources in your program; you can then adjust their configuration in a separate update." It explains the…; source: repo:content/blog/component-state-migrations/index.md L112-116
source: repo:content/blog/component-state-migrations/index.md L112-116
pass1 · behavior · medium confidence
#54 ➖ Not a claim
content/blog/component-state-migrations/index.md:142
That makes the upgrade path part of the reusable building block. You write and test it once, and each team using the component gets it with the new version.
evidence: This sentence is the author's own editorial point about why component state migrations help: the upgrade logic is written once and ships with the component. It makes no third-party, numeric or dated assertion that could be checked. The…; source: content/blog/component-state-migrations/index.md L142 (claim text only; no external source cited)
source: content/blog/component-state-migrations/index.md L142 (claim text only; no external source cited)
pass3 · temporal · high confidence
#4 🤷 Unverifiable
content/blog/component-state-migrations/index.md:19
The GitHub repository at https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration contains all three example programs (v1, v2, v3) and…
framing: The page loads, but the fetched body says nothing about the directory's contents.; evidence: The cited URL returned HTTP 200 with the page title "examples/aws-ts-awsx-vpc-state-migration at master · pulumi/examples · GitHub", so the directory appears to exist. The fetched body was cut off after the title and does not list any…; source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
framing: The page loads, but the fetched body says nothing about the directory's contents.
pass2 · url · low confidence
#10 🤷 Unverifiable
content/blog/component-state-migrations/index.md:39
The AWSX VPC example at github.com/pulumi/examples follows a network through three versions of code: v1, v2, and v3, where you start with v1, upgrade to v2…
framing: The page was fetched, but its truncated body doesn't cover the claim. A gh contents listing of pulumi/examples/aws-ts-awsx-vpc-state-migration would settle it.; evidence: The cited directory exists (HTTP 200), but the pre-fetched body only contains the page title, "examples/aws-ts-awsx-vpc-state-migration at master · pulumi/examples · GitHub". It doesn't list the directory contents or README, so I…; source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
framing: The page was fetched, but its truncated body doesn't cover the claim. A gh contents listing of pulumi/examples/aws-ts-awsx-vpc-state-migration would settle it.
pass2 · url · low confidence
#14 🤷 Unverifiable
content/blog/component-state-migrations/index.md:43
Without a state migration connecting old state to new code, upgrading the AWSX VPC component could replace the VPC instead of keeping it.
framing: shifted: the source says changing a security group's VpcId forces replacement of the security group, but the claim says upgrading the AWSX VPC component…; evidence: The cited page loaded (200) but it is the CloudFormation reference for AWS::EC2::SecurityGroup. Its only relevant line is about the security group's VpcId: "VpcId The ID of the VPC for the security group... Update requires …; source: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html#cfn-ec2-securitygroup-vpcid; intuition: The link looks misplaced. A page on security-group VpcId replacement doesn't back a claim about VPC replacement…
source: https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-ec2-securitygroup.html#cfn-ec2-securitygroup-vpcid
framing: shifted — shifted: the source says changing a security group's VpcId forces replacement of the security group, but the claim says upgrading the AWSX VPC component without a migration could replace the VPC itself.
pass2 · url · medium confidence
#55 🤷 Unverifiable
content/blog/component-state-migrations/index.md:144
The VPC example at https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration contains all three programs and the migration code shown in…
framing: The source only shows the directory exists. It says nothing about what's inside ("all three programs and the migration code").; evidence: The cited URL returned HTTP 200 with the page title "examples/aws-ts-awsx-vpc-state-migration at master · pulumi/examples · GitHub", so the directory exists. The fetched body was only that title, with no directory listing, so I couldn't…; source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
source: https://github.com/pulumi/examples/tree/master/aws-ts-awsx-vpc-state-migration
framing: overclaim-broader — The source only shows the directory exists. It says nothing about what's inside ("all three programs and the migration code").
pass2 · url · low confidence

Findings

IDBucketFile:linesStatusDisposition
F5 ⚠️ Reviewer check content/blog/component-state-migrations/index.md:45 open fixed
F1 ❓ Author answer content/blog/component-state-migrations/index.md conceded —
F2 ❓ Author answer content/blog/component-state-migrations/index.md conceded fixed
F3 ❓ Author answer content/blog/component-state-migrations/index.md conceded —
F4 ❓ Author answer content/blog/component-state-migrations/index.md conceded fixed

Editorial stances

The extractor found no positioning or comparison language in this PR's added lines.

Investigation log

cross-sibling-reads
0 of 22 siblings
external-claim-verification
53 of 62 claims verified (4 unverifiable, 0 contradicted) · 4 specialists (numerical, cross-reference, capability, framing); 0 cross-specialist corroborations · routed: 0 inline, 47 Pass 1, 9 Pass 2 (verified 5, contradicted 0, unverifiable 4), 6 Pass 3 (verified 2, contradicted 0, unverifiable 4).
cited-claim-spot-checks
9 of 9 cited claims fetched and compared
frontmatter-sweep
ran on body + meta_desc
temporal-trigger-sweep
ran (recency words present in diff; spot-check in-review)
code-execution
ran static/programs/awsx-vpc-state-migration-blog-typescript (CI test harness gates parse + imports)
code-examples-checks
ran (3 specialists: structural, existence, body-code-coverage); 0 findings
editorial-balance-pass
ran (single-subject, N/A)

Editorial balance

{
  "files": [
    {
      "file": "content/blog/component-state-migrations/index.md",
      "outliers": [
        {
          "heading": "One VPC, three versions of the code",
          "lines": 29,
          "ratio": 4.8
        }
      ],
      "sections": [
        {
          "heading": "One VPC, three versions of the code",
          "lines": 29
        },
        {
          "heading": "Why a change in code needs a change in state",
          "lines": 3
        },
        {
          "heading": "The first migration: from legacy to modern AWSX",
          "lines": 14
        },
        {
          "heading": "The second migration: from AWSX to plain AWS resources",
          "lines": 8
        },
        {
          "heading": "Check the upgrade before applying it",
          "lines": 3
        },
        {
          "heading": "Ship the migration with your component",
          "lines": 4
        }
      ],
      "stats": {
        "mean": 10.2,
        "median": 6.0,
        "std": 9.3
      },
      "threshold_flags": [
        {
          "heading": "One VPC, three versions of the code",
          "lines": 29,
          "ratio": 4.8,
          "type": "section-depth-3x-median"
        }
      ]
    }
  ],
  "trigger": null
}

History

  1. 2026-09-25T14:48:35Z 3cf8eb5

    initial review (pending publication)

  2. 2026-09-25T15:18:28Z 3cf8eb5340

    @CamSoper confirmed F1–F4; examples dir listing (v1/v2/v3) corroborates F1/F2; all four conceded