XanCloud/xancloud-iac, blueprints/landing-zone-basic (an AWS landing-zone accelerator: VPC + CloudTrail + account-level IAM baseline), pinned by tag v0.2.0 and commit 7bc78ff79df4f914921cf04fd9728d09526c93bd
Source: https://github.com/XanCloud/xancloud-iac.git at v0.2.0.
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.
| Stage | Verdict | Detail |
|---|---|---|
| Cold deploy | pass | 28 resources, genuinely cold, genuinely unmarked |
| Migrate | pass | live-import -approve completed cleanly against the cold state |
| Replan from nothing | pass | no resource change proposed |
| No-op apply | pass | genuine no-op (0 added, 0 changed, 0 destroyed); tofu-estate-tagged object count unchanged at 21 |
| Drift and reconverge | pass | one object tampered (Name tag), exactly module.vpc.aws_vpc.this[“main”] proposed by both choudoufu and stock with the identical change, apply changed 1 and the Name tag reads back as configured |
| Rename | pass | moved block: aws_iam_role.flow_logs renamed with zero churn (0 add, 1 change, 0 destroy), marker rewritten in place; live-mv: aws_eip.nat renamed with zero churn, marker rewritten in place; stock oracle over the same two-object 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 block | pass | choudoufu: deleting aws_vpc_endpoint.s3’s block (the S3 gateway endpoint, a standalone leaf nothing else in the module references) proposed exactly one destroy (0 add, 0 change, 1 destroy), applied cleanly (0 added, 0 changed, 1 destroyed), the endpoint is genuinely gone from the live account (describe-vpc-endpoints on the old id reports State=deleted or nothing at all, read via the AWS CLI, not choudoufu’s own report), and the next plan is empty; the E-ORACLE stock oracle (on cold_deploy’s own state, before any tag was ever written) also proposes exactly one destroy for the same object; classifyOrphans did not withhold the destroy because no other aws_vpc_endpoint.s3 block is declared anywhere in this config |
| Change count (planned) | pass | choudoufu: dropping “logs” from var.vpcs.main.vpc_endpoints destroyed exactly module.vpc.aws_vpc_endpoint.interface[“main-logs”] (0 add, 0 change, 1 destroy), leaving every sibling for_each member (main-ssm’s live id and tofu-address marker checked directly) untouched; adding it back created exactly the same key under a NEW live id (0 add -> 1 add, 0 change, 0 destroy) while main-ssm stayed untouched throughout; the next plan is empty; the F-ORACLE stock oracle on the identical for_each set, applied on cold_deploy’s own state, shows the identical shape: destroy the dropped key only, create it back under a new id, every sibling key’s id unchanged both times |
| Replace with create_before_destroy | not run | |
| Crash between create and destroy (planned) | not run | |
| Teardown (planned) | not run | |
| Plan, review, apply (planned) | not run | |
| Greenfield apply | pass | 28 resources from nothing (matching stage 1’s stock cold-deploy count exactly), all markers verified via the AWS CLI, 28 records in the local record store (#364 A2), replan empty, object-by-object comparison against stock’s still-pristine cold deploy on $ENDPOINT matches on tagged-object count (21), VPC CIDR, subnet/NAT-gateway/VPC-endpoint counts and account alias |
| Strict profile (planned) | not run |
Last run at commit a4c4d76883 on 2026-08-25T18:20:03Z, exit code 0.
Landed 2026-08-19, the fifth OpenTofu-native estate. Genuinely different from every prior crossing in this lane. OpenTofu-native evidence: README/badges state “OpenTofu-first … native state encryption, S3 locking without DynamoDB, no vendor lock-in”, required_version >= 1.11.0, and docs/TROUBLESHOOTING.md carries a dedicated real-usage “OpenTofu general” section (tofu init -upgrade) rather than just a badge - weaker than corpus-hongbomiao’s genuine .tofu files (this ships plain .tf), comparable to sumaform/overture-tiles. Several other candidates evaluated and rejected first (an account-singleton-heavy 0-star repo, a devtool’s test fixture masquerading as an estate, multiple 0-1-star scaffolds). cold_deploy genuinely passes (28 resources, plain tofu apply, unmodified). migrate genuinely passes: live-import 22 of 28 eligible (21 VERIFIED, 1 DRIFTED), -approve 22 newly stamped, 6 correctly UNTAGGABLE, 0 failed. test_plan BLOCKED, deterministically asserted (Plan: 2 to add, 3 to change, 1 to destroy, all 5 addresses traced to three independent, filed, evidence-backed gaps, not routed around); the VPC’s own marker re-verified directly against the AWS CLI after state deletion, BREAK=1 confirmed load-bearing. Six real floci gaps filed with full evidence: lex00/floci#73 (S3Control PutPublicAccessBlock unimplemented), #74 (IAM UpdateAccountPasswordPolicy unsupported), #75 (IAM Access Analyzer - whole missing service), #76 (EC2 ModifyInstanceMetadataDefaults unsupported), #77 (CloudTrail tagging trio missing, blocks any tagged aws_cloudtrail), #78 (EC2 CreateFlowLogs ignores TagSpecifications) - none fixed, per this session’s standing instruction. Two choudoufu gaps filed: INTENTIUS/choudoufu#327 (aws_nat_gateway’s ForceNew args read null from a stateless prior, forcing a spurious replace), #328 (aws_default_security_group.revoke_rules_on_delete, write-only with no live representation, always diffs) - not fixed. A REAL BUG found and fixed along the way, outside this task’s own estate work: #325’s marker-alias fix (merged just before this crossing started) double-counted a live object when an estate declares BOTH sides of a default-adopter pair (this module does, aws_default_security_group next to an unrelated aws_security_group) - both scanType passes appended an identical claimant, producing a false “Two live resources claiming one address” collision on a single real object (confirmed via direct AWS CLI query). Fixed with claimantAlreadyPresent (dedupe by import ID), covered by a new regression test reproducing the exact real-world error text before the fix and passing after. Stages 4-5 not attempted - both need a genuinely empty first plan. Merged to local main as 62e63a3eb5 (crossing: 427977009a, the discovery double-count fix: 3bdceb43e3); rebased onto a concurrent sibling’s internal/live/identity work mid-session, one conflict (the generated identity-golden.txt) resolved by regenerating, not hand-merging; justfile gained recipe demo-corpus-xancloud-iac; live/corpus-manifest.json gained the pin. Re-verified 2026-08-19 after #327’s fix (56e807062e/b5bb09d27e, generic - reuses #275’s existing residueCandidates/ResidueStore mechanism unchanged, adding one new call site: live-import’s Approve now records residue for every eligible instance using the migrated state’s own real prior value, not #327-specific): plan moved from 2 to add/3 to change/1 to destroy down to 1 to add/1 to change/0 to destroy - aws_nat_gateway.this[“main-0”] no longer proposes a spurious replace. Remaining test_plan blockers are exactly the still-unfixed floci gaps (#73-#78, S3Control/IAM password policy/IAM Access Analyzer/EC2 metadata defaults/CloudTrail tagging/EC2 flow logs), not a choudoufu-side gap. A residual, lower-severity, choudoufu-specific diff on regional_nat_gateway_address (pure-Computed set(object), harmless) remains and was deliberately not filed - residueCandidates correctly excludes pure-Computed attributes, and broadening that needs its own corpus-wide validation before it’s safe (risk: masking real out-of-band drift). Follow-up pass 2026-08-20 (this session): #73/#74/#75 fixed and closed (lex00/floci commits 51c00478/08d92407/be3f7ffd - S3 account-level PutPublicAccessBlock, IAM UpdateAccountPasswordPolicy, AccessAnalyzer as a whole new service), joining #76/#77/#78 which other concurrent sessions closed the same night (all six of the floci gaps this estate originally filed are now closed). Re-pinned floci-image to be3f7ffd (sha256:8a882bcc, CI+GHCR-publish both green) and regenerated floci-capabilities.json (verified additive: one digest block added, none removed, no existing block changed). Re-crossed for real against the new pin, the script AS COMMITTED (still setting TF_VAR_cloudtrail_enabled=false and the three iam_baseline_enable_* toggles off, so the five originally-toggled-off features are not re-exercised by this run - re-enabling them is separate, larger follow-up work, not attempted here). Real result: stage 1 PASS (28 resources, unchanged); stage 2 PASS (22 stamped: 21 VERIFIED + 1 DRIFTED, 6 UNTAGGABLE, 0 failed - unchanged from before); stage 3 still FAILS the script’s own hard-coded assertion (which expects the stale ‘Plan: 2 to add, 3 to change, 1 to destroy.’ shape from before tonight’s floci fixes), but the REAL diagnostic surface changed: only two addresses appear in the plan now, not five - ‘module.vpc.aws_nat_gateway.this[“main-0”] will be updated in-place’ (the pre-existing, previously-noted harmless regional_nat_gateway_address residual, #327 itself still holding - no force-replace) and, newly, ‘module.vpc.aws_flow_log.cloudwatch[“main”] must be replaced’ - a force-replace that could not appear before tonight because the flow log was never migrated at all (floci#78 blocked its tag write, so live-import never had a marker to find). This is very likely the same #327-shaped bug class (a ForceNew argument reading null from a stateless prior) now hitting aws_flow_log instead of aws_nat_gateway, not yet diagnosed or filed as its own issue - flagged here rather than assumed. A second confirmatory run was attempted to capture the exact ‘Plan: N to add, M to change, K to destroy’ totals line and pin down the flow_log diff further, but was lost to a session interruption before completing; the two-address finding above is from one complete, real, natural-exit run and was not re-confirmed a second time this session. The script’s own hard-coded assertion (both the exact-string check and the per-address list) is now stale relative to the pin and needs updating by whoever picks this back up, once the flow_log diff is diagnosed. Stages 4-5 remain not_run (unchanged - both need a genuinely empty first plan, which this has not yet reached). RESOLVED as #347 (2026-08-20, 2cb473affd/27cafb1650): the flow_log diff was diagnosed - iam_role_arn (ForceNew) reads null on the stateless prior because floci’s own FlowLogService never learns or emits it at all (Ec2QueryHandler.handleCreateFlowLogs ignores DeliverLogsPermissionArn; handleDescribeFlowLogs never returns it), confirmed via TF_LOG=trace straight through Ratification.Approve’s residue classification (#327’s residueCandidates/ResidueStore mechanism correctly DECLINES to record it, since both classification reads come back empty on any prior, not just the stateless one - the opposite of #327’s shape, where the provider preserves without truly reading). Confirmed parity label 1, “OpenTofu fails here too”: the PLAIN cold-deploy state (written by a real, non-choudoufu tofu apply) already carries iam_role_arn="" immediately after apply, so a stock stateful tofu plan would show the identical perpetual diff. Filed as lex00/floci#87 (open, emulator gap, not a choudoufu defect). run.sh’s stage-3 assertions were updated to match reality: 2 addresses (aws_flow_log.cloudwatch[“main”] must be replaced; aws_nat_gateway.this[“main-0”] will be updated in-place, #327’s own still-harmless residual) and “Plan: 1 to add, 1 to change, 1 to destroy.” RE-VERIFIED 2026-08-21 (this session, worktree live/reverify-limitations, floci pinned at the current e61a987/d65baf42 image): real re-run of run.sh, exit 0, every hard-coded assertion passed byte-for-byte against the #347 shape above - same 2 addresses, same summary line, same 28/22/21+1/6/0 stage 1-2 counts. lex00/floci#87 confirmed still OPEN (not narrowed by the e61a987 re-pin, which addressed #86/#88 only). None of tonight’s #331/#337/#340/#343/#344 admission/identity/record-store changes touched this estate. Wall unchanged; stages 4-5 remain not_run. UPDATE 2026-08-21 (lex00/floci#87 FIXED via lex00/floci#96, PR squash-merged as 17c7f7ef, published sha256:cdd50ec04a1a13461035657bdd9ec2ed377ac48925e76495a73c9674b5cbd9f9, verified via the GHCR packages API and docker buildx imagetools inspect on both the :17c7f7e and :latest tags): CreateFlowLogs/DescribeFlowLogs now carry DeliverLogsPermissionArn. Re-pinned floci-image to this digest and regenerated floci-capabilities.json (verified additive: one digest block added - 87 services, 747 type rows, matching every prior digest’s shape - none removed, no existing block changed). Re-crossed for real against the new pin: stage 1 PASS (28 resources, unchanged); stage 2 PASS (22 stamped: 21 VERIFIED + 1 DRIFTED, 6 UNTAGGABLE, 0 failed - unchanged from before). Stage 3 (test_plan) genuinely changed shape: aws_flow_log.cloudwatch[“main”] no longer appears anywhere in the plan - the force-replace lex00/floci#87 caused is gone. The plan is narrower but NOT empty: ‘Plan: 0 to add, 1 to change, 0 to destroy.’, the sole remaining address module.vpc.aws_nat_gateway.this[“main-0”] will be updated in-place - the same pre-existing, harmless #327 regional_nat_gateway_address residual this estate has carried since before #87 was ever diagnosed. run.sh’s stage-3 header and assertions rewritten to match this reality (single-address plan, exact ‘Plan: 0 to add, 1 to change, 0 to destroy.’ string, an explicit assertion that aws_flow_log no longer appears), re-run clean end to end (exit 0, no FAIL), and BREAK=1 re-confirmed load-bearing (the VPC identity check fails exactly as designed against a wrong expected address). test_plan stays ‘fail’ by this repo’s own convention (a first plan must be empty to pass) - #327’s own NAT-gateway residual is the estate’s only remaining wall, unchanged in kind from before, just no longer sharing the plan with #87. Stages 4-5 remain not_run: both still need a genuinely empty first plan, which this estate has not yet reached. NOT a new estate at full parity - one wall cleared (lex00/floci#87), one wall (#327, already tracked, not this session’s to fix) remains. UNIT gauntlet:corpus-xancloud-iac/test_plan (2026-08-21, orchestrator-run worker): stage 3 (test_plan) is now PASS. Root cause traced and fixed generically, not scoped around: aws_nat_gateway.this[“main-0”] regional_nat_gateway_address (Computed only - this NAT gateway has connectivity_type=public, not “regional”, confirmed directly against floci’s own DescribeNatGateways response, which carries no such field for this object at all) was showing “+ regional_nat_gateway_address = (known after apply)” on every stateless first plan. internal/live/projection/residue.go’s residueCandidates and fillResidue used to refuse a purely-Computed attribute a residue candidacy at all (“it cannot be set in configuration, so there is nothing to remember”) - that reasoning undercounted a real case: the provider’s Read does not re-derive this attribute from a bare identity-only prior, it leaves whatever the prior held (null), and OpenTofu marks a null Computed attribute unknown forever. Fixed by dropping the Required/Optional restriction from both functions, keeping every other exclusion (identity, sensitive, write-only, NestedType) - safety comes from classifyResidue’s own two-read discriminator, not from that schema-shape filter. internal/live/projection/residue_test.go and internal/live/liveimport/residue_test.go updated to match (arn, Computed-only in the lambda-like fixture, is now a legitimate candidate; a new TestFillResidueFillsAComputedOnlyAttribute pins the positive case). Re-crossed for real: stage 1 PASS (28 resources, unchanged); stage 2 PASS (22 stamped, unchanged); stage 3 now PASS - “No changes. Your infrastructure matches the configuration.”, BREAK=1 re-confirmed load-bearing against the VPC identity check. Stages 4-5 remain not_run: not yet written, since stage 3 only just started passing in this run - a follow-up unit’s work, not attempted here.
Reproduce it#
go run ./tools/gauntlet run corpus-xancloud-iacNeeds 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-xancloud-iac/run.sh; BREAK=1 corrupts its assertions to show they are load-bearing.