giantswarm/giantswarm-aws-account-prerequisites, the crossplane/ module (pinned tag v8.2.2, commit f1a7d8d51086824a97749b1a8a13327c6f081f72)

Source: https://github.com/giantswarm/giantswarm-aws-account-prerequisites.git at v8.2.2.

Set: core. Lane: opentofu-native.

Why it is in the core set: a real project built for OpenTofu specifically, so OpenTofu-only surface is exercised

Not clear yet.

StageVerdictDetail
Cold deploypass6 resource instances added, 0 already tofu-estate-marked before migration
Migratepass2 of 6 stamped (role, managed policy), 4 untaggable skipped, module’s own tags survived the stamp
Replan from nothingpasslive-plan empty, role/policy tofu-address unchanged, both *_exclusive resources re-derived by value
No-op applypassno-op apply (0 added, 0 changed, 0 destroyed); object count unchanged at 2, both exclusive sets unchanged
Drift and reconvergepassrole’s installation tag tampered, exactly the IAM role proposed and reconciled, apply changed 1, tag reads back as configured
Renamepassmoved block: module.crossplane renamed to .crossplane_renamed with zero churn (0 add, 2 change, 0 destroy - role and policy), markers rewritten in place; live-mv: .crossplane_renamed renamed to .crossplane_final with zero churn, both markers rewritten in place (one live-mv call per taggable object); stock oracle over the same chained module rename on cold_deploy’s own state also shows zero churn (0 add, 0 change, 0 destroy); both live ids unchanged, read via the AWS CLI
Remove a blockpasschoudoufu: deleting module.crossplane_final’s block proposed 6 resource action(s), address-for-address and action-for-action identical to stock’s oracle on cold_deploy’s own state; applied cleanly; the role is genuinely gone from the live account (get-role now returns NoSuchEntity, read via the AWS CLI, not choudoufu’s own report); classifyOrphans did not withhold any destroy because no other module.crossplane* block is declared anywhere in this config; the next plan is empty
Change count (planned)not run
Replace with create_before_destroynot run
Crash between create and destroy (planned)not run
Teardown (planned)not run
Plan, review, apply (planned)not run
Greenfield applypass6 resources from nothing (role, managed policy, 4 untaggable), role marker verified via the AWS CLI, 6 records in the local record store (#364 A2, one per managed instance), replan empty, stock oracle in its own namespace matches structurally on the role and the managed policy
Strict profile (planned)not run

Last run at commit 7ff51b84d3 on 2026-08-25T17:26:53Z, exit code 0.

Landed 2026-08-19 (crossing 0bd3ac80b7, merge 9fa0141294), the seventh OpenTofu-native estate and the first from a commercial vendor’s production repository rather than a module registry, personal monorepo, or single-maintainer accelerator - Giant Swarm GmbH’s own customer-facing account-prep for their managed Kubernetes offering. OpenTofu-native evidence, three independent kinds: README’s opening sentence and directory index both say OpenTofu with no compatibility hedge; the CI workflow is named ‘OpenTofu checks’, installs via opentofu/setup-opentofu, and never mentions terraform; the crossed crossplane/ directory is genuinely .tofu-suffixed throughout (providers.tofu, role.tofu, variables.tofu), the file-level standard only the hongbomiao slices had met before (overture-tiles and xancloud-iac are both plain .tf). Scoped to crossplane/ specifically: self-contained (no remote state, no live EKS/OIDC dependency, its only data source is aws_partition which makes no API call), the other five directories in the repo excluded with stated reasons (three plain-.tf same-shape, one an account-singleton quota table, one a wrapper that only calls the others). Real run, rc=0, 548s. cold_deploy: PASS, plain tofu apply, 6 resources added, 0 pre-existing tofu-estate tags, the toset()-keyed for_each on additional_policy_attachments confirmed resolving to zero instances. migrate: PASS - 2 of 6 eligible (UNTAGGABLE 2, UNADMITTED_TYPE 2, DRIFTED 2), -approve 2 newly stamped 0 failed, both markers re-verified directly through the AWS CLI including that the module’s own installation tag survived the stamp. test_plan: BLOCKED for real at exactly 2 sites, the plan’s entire diagnostic surface - both Rule: unadmitted-type, on aws_iam_role_policy_attachments_exclusive and aws_iam_role_policies_exclusive, no other rule firing anywhere in the estate. A control stage (3b, not counted toward stage 4/5) cut exactly those two resource blocks and drove the rest of the pipeline for real: control test plan EMPTY, control test apply a genuine no-op (2 objects before and after), control drift-and-reconverge fixed exactly one mutated object - proving the estate’s only real block is those two types, not routing around anything. Both negative controls (BREAK=1 at the stage-2 identity assertion, BREAK_STAGE3=1 expecting 3 refusal sites where the real count is 2) verified failing in real full runs. Filed as INTENTIUS/choudoufu#334: both unadmitted types have the identical import-grammar shape (single-argument, no-separator) to aws_vpc_security_group_rules_exclusive, which #307 already admitted via row-gen’s tryGrammarComposite at 64cac28120, and carry the same no-CFN-counterpart mapping-gen overlay as that admitted twin - a worked ADMIT-class precedent, not attempted here; the one recorded difference (force_new on the admitted twin’s security_group_id, absent on either new type’s role_name) is flagged as not obviously the gate since tryGrammarComposite’s single-argument branch reads no force_new field, and why row-gen’s own proposal for these two is currently absent from ratified.json is the fix’s first open question. No Go code touched. justfile gained demo-corpus-giantswarm-crossplane; live/corpus-manifest.json gained the pin; HANDOFF.md section 3 updated. Follow-up pass 2026-08-19/20 (#334 fixed and merged, 37957d873c/a6627543c4/20cc1774d6): the issue’s own open question resolved the OPPOSITE way from what it suspected - row-gen was never declining to propose these two rows; it proposes both, byte-identical in shape to the admitted aws_vpc_security_group_rules_exclusive twin, and nobody had ever ratified the proposal. Fix is a ratified.json entry, no code change - reach is exactly these two types, stated plainly rather than dressed up as a generalization. The real finding: 316 types row-gen proposes sit unratified, 166 under this exact rule (including every other *_exclusive family member) - a ratification backlog, not a generator defect, and clearing it is a maintainer-scale call since every ratified row is a claim that touches live infrastructure. FIVE OF FIVE, run for real on the rebased tree, rc=0, 250s: stage 3 now an empty plan (identities asserted by value - the two exclusive resources carry no marker, being untaggable, so the assertion is the live content each enforces, e.g. attached policy ARN and inline-policy name); stage 4 a genuine no-op (2 tagged objects before and after, both exclusive sets independently re-read afterward so a wrongly-reconciled enforcer would be caught); stage 5 one out-of-band mutation, exactly one object proposed and fixed. Three real negative controls (BREAK=1, BREAK_STAGE3=1, BREAK_STAGE5=1) each confirmed failing at the right point. Script rewritten: stage 3 now asserts a pass instead of hard-failing by design, the 3b control retired with the block it existed to control for. Separately found, not yet fixed: every crossing script that runs more than one terraform init pays a real ~320s tax per extra init, because the shared plugin cache records no checksums and a directory with no .terraform.lock.hcl re-downloads the whole provider to compute them - seeding the lock file from stage 1’s own init cuts this to ~1s and this estate’s full run from several failed 10-minute-cap attempts to 250s total. Worth a sweep across every multi-init script here.

Reproduce it#

go run ./tools/gauntlet run corpus-giantswarm-crossplane

Needs Docker (the emulator is pulled at the pinned digest), the AWS CLI, and a stock terraform or tofu binary on PATH for the cold deploy. The script is live/e2e/corpus-giantswarm-crossplane/run.sh; BREAK=1 corrupts its assertions to show they are load-bearing.