Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package opentofu for openSUSE:Factory 
checked in at 2026-05-29 18:08:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/opentofu (Old)
 and      /work/SRC/openSUSE:Factory/.opentofu.new.1937 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "opentofu"

Fri May 29 18:08:41 2026 rev:49 rq:1355775 version:1.12.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/opentofu/opentofu.changes        2026-05-16 
19:27:10.456550323 +0200
+++ /work/SRC/openSUSE:Factory/.opentofu.new.1937/opentofu.changes      
2026-05-29 18:10:20.090418031 +0200
@@ -1,0 +2,24 @@
+Fri May 29 06:48:34 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 1.12.1:
+  Full Changelog:
+  https://github.com/opentofu/opentofu/blob/v1.12/CHANGELOG.md
+  * SECURITY ADVISORIES:
+    - Previous releases in the v1.12 series could be affected by
+      several vulnerabilities:
+      - ssh usage through OpenTofu generate hangs or panics.
+      - Previously, a revoked 'SignatureKey' belonging to a CA was
+        not correctly checked for revocation. Now, both the 'key'
+        and 'key.SignatureKey' are checked for @revoked.
+      This is fixed now by (#4145)
+  * BUG FIXES:
+    - Address a bug introduced in v1.12.0 causing excessive memory
+      usage by providers. (#4126)
+    - Address a bug introduced in v1.12.0 where
+      replace_triggered_by was validated incorrectly. (#4133
+    - The Azure key provider will now accept the tenant_id,
+      subscription_id, environment, and metadata_host variables; a
+      bug previously only allowed these to be set through
+      environment variables. (#4091)
+
+-------------------------------------------------------------------

Old:
----
  opentofu-1.12.0.obscpio

New:
----
  opentofu-1.12.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ opentofu.spec ++++++
--- /var/tmp/diff_new_pack.J8wOX5/_old  2026-05-29 18:10:21.118462273 +0200
+++ /var/tmp/diff_new_pack.J8wOX5/_new  2026-05-29 18:10:21.122462445 +0200
@@ -19,7 +19,7 @@
 %define executable_name tofu
 
 Name:           opentofu
-Version:        1.12.0
+Version:        1.12.1
 Release:        0
 Summary:        Declaratively manage your cloud infrastructure
 License:        MPL-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.J8wOX5/_old  2026-05-29 18:10:21.174464684 +0200
+++ /var/tmp/diff_new_pack.J8wOX5/_new  2026-05-29 18:10:21.178464856 +0200
@@ -1,9 +1,9 @@
 <services>
   <service name="obs_scm" mode="manual">
-    <param name="url">https://github.com/opentofu/opentofu/</param>
+    <param name="url">https://github.com/opentofu/opentofu.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">v1.12.0</param>
+    <param name="revision">refs/tags/v1.12.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.J8wOX5/_old  2026-05-29 18:10:21.202465889 +0200
+++ /var/tmp/diff_new_pack.J8wOX5/_new  2026-05-29 18:10:21.206466061 +0200
@@ -1,6 +1,8 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/opentofu/opentofu/</param>
-              <param 
name="changesrevision">bdcbf091aab886499ed7718d7f558b428fffce39</param></service></servicedata>
+              <param 
name="changesrevision">bdcbf091aab886499ed7718d7f558b428fffce39</param></service><service
 name="tar_scm">
+                <param 
name="url">https://github.com/opentofu/opentofu.git</param>
+              <param 
name="changesrevision">dc29882638869cdc60f871a112a04a415042caf1</param></service></servicedata>
 (No newline at EOF)
 

++++++ opentofu-1.12.0.obscpio -> opentofu-1.12.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/CHANGELOG.md 
new/opentofu-1.12.1/CHANGELOG.md
--- old/opentofu-1.12.0/CHANGELOG.md    2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/CHANGELOG.md    2026-05-27 10:51:46.000000000 +0200
@@ -1,6 +1,20 @@
 The v1.12.x release series is supported until **February 1 2027**.
 
-## 1.12.1 (Unreleased)
+## 1.12.1
+
+SECURITY ADVISORIES:
+
+* Previous releases in the v1.12 series could be affected by several 
vulnerabilities:
+  * ssh usage through OpenTofu generate hangs or panics.
+  * Previously, a revoked 'SignatureKey' belonging to a CA was not correctly 
checked for revocation. Now, both the 'key' and 'key.SignatureKey' are checked 
for @revoked.
+
+  This is fixed now by 
([#4145](https://github.com/opentofu/opentofu/pull/4145))
+
+BUG FIXES:
+
+- Address a bug introduced in v1.12.0 causing excessive memory usage by 
providers. ([#4126](https://github.com/opentofu/opentofu/pull/4126))
+- Address a bug introduced in v1.12.0 where `replace_triggered_by` was 
validated incorrectly. ([#4133](https://github.com/opentofu/opentofu/pull/4133)
+- The Azure key provider will now accept the `tenant_id`, `subscription_id`, 
`environment`, and `metadata_host` variables; a bug previously only allowed 
these to be set through environment variables. 
([#4091](https://github.com/opentofu/opentofu/issues/4091))
 
 ## 1.12.0
 
@@ -32,6 +46,7 @@
 - New `lifecycle` meta-argument `destroy`: when set to `false` OpenTofu will 
plan to just remove the affected object from state without asking the provider 
to destroy it first, similar to `destroy = false` in `removed` blocks. 
([#3409](https://github.com/opentofu/opentofu/pull/3409))
 - Comparing an object or other complex-typed value to `null` using the `==` 
operator now returns a sensitive boolean result only if the object as a whole 
is sensitive, and not when the object merely contains a sensitive value nested 
inside one of its attributes. This means that comparisons to null can now be 
used in parts of the configuration where sensitive values are not allowed, such 
as in the `enabled` meta-argument on resources and modules. 
([#3793](https://github.com/opentofu/opentofu/pull/3793))
 - Resources using `replace_triggered_by` in their `lifecycle` block are now 
replaced when a resource they refer to is itself being replaced, whereas before 
this triggered only when it was being updated. 
([#3714](https://github.com/opentofu/opentofu/issues/3714))
+- `import` blocks now allow describing the object to be imported using an 
object matching the resource type's _identity schema_ using the `identity` 
argument, instead of just a plain string using the `id` argument. 
([#3671](https://github.com/opentofu/opentofu/pull/3671))
 - OpenTofu now produces warnings for any references to attributes or blocks of 
a resource type that are marked as deprecated in the provider schema, unless 
disabled by the `-deprecation=` option. 
([#3973](https://github.com/opentofu/opentofu/pull/3973/))
 - The `yamldecode` function now supports the "merge" tag, most commonly 
written as `<<` where a map key would be expected, with sequences of mappings 
rather than just individual mappings. 
([#3607](https://github.com/opentofu/opentofu/pull/3607))
 - A new configuration block type `language` offers a more general way to 
define version constraints that separates OpenTofu constraints from other 
software. Note that module authors should delay adopting this new syntax until 
they are ready to require OpenTofu v1.12.0 or later, but there is an interim 
solution available that is backward-compatible with earlier OpenTofu versions. 
([#3300](https://github.com/opentofu/opentofu/issues/3300))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/go.mod new/opentofu-1.12.1/go.mod
--- old/opentofu-1.12.0/go.mod  2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/go.mod  2026-05-27 10:51:46.000000000 +0200
@@ -102,14 +102,14 @@
        go.opentelemetry.io/otel/sdk v1.42.0
        go.opentelemetry.io/otel/trace v1.42.0
        go.uber.org/mock v0.6.0
-       golang.org/x/crypto v0.49.0
-       golang.org/x/mod v0.34.0
-       golang.org/x/net v0.52.0
+       golang.org/x/crypto v0.52.0
+       golang.org/x/mod v0.35.0
+       golang.org/x/net v0.54.0
        golang.org/x/oauth2 v0.36.0
        golang.org/x/sync v0.20.0
-       golang.org/x/sys v0.42.0
-       golang.org/x/term v0.41.0
-       golang.org/x/text v0.35.0
+       golang.org/x/sys v0.45.0
+       golang.org/x/term v0.43.0
+       golang.org/x/text v0.37.0
        google.golang.org/api v0.271.0
        google.golang.org/grpc v1.79.3
        google.golang.org/protobuf v1.36.11
@@ -299,7 +299,7 @@
        golang.org/x/exp v0.0.0-20250808145144-a408d31f581a // indirect
        golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // 
indirect
        golang.org/x/time v0.15.0 // indirect
-       golang.org/x/tools v0.42.0 // indirect
+       golang.org/x/tools v0.44.0 // indirect
        google.golang.org/genproto v0.0.0-20260217215200-42d3e9bedb6d // 
indirect
        google.golang.org/genproto/googleapis/api 
v0.0.0-20260226221140-a57be14db171 // indirect
        google.golang.org/genproto/googleapis/rpc 
v0.0.0-20260226221140-a57be14db171 // indirect
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/go.sum new/opentofu-1.12.1/go.sum
--- old/opentofu-1.12.0/go.sum  2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/go.sum  2026-05-27 10:51:46.000000000 +0200
@@ -926,8 +926,8 @@
 golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod 
h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod 
h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod 
h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
-golang.org/x/crypto v0.49.0/go.mod 
h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
+golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988=
+golang.org/x/crypto v0.52.0/go.mod 
h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -951,8 +951,8 @@
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
-golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
+golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
+golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -974,8 +974,8 @@
 golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod 
h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod 
h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20220923203811-8be639271d50/go.mod 
h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
-golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
-golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
+golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w=
+golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod 
h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1039,13 +1039,13 @@
 golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod 
h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
-golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
+golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
+golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod 
h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod 
h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod 
h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
-golang.org/x/term v0.41.0/go.mod 
h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
+golang.org/x/term v0.43.0 h1:S4RLU2sB31O/NCl+zFN9Aru9A/Cq2aqKpTZJ6B+DwT4=
+golang.org/x/term v0.43.0/go.mod 
h1:lrhlHNdQJHO+1qVYiHfFKVuVioJIheAc3fBSMFYEIsk=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod 
h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -1053,8 +1053,8 @@
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
-golang.org/x/text v0.35.0/go.mod 
h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
+golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
+golang.org/x/text v0.37.0/go.mod 
h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod 
h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
 golang.org/x/time v0.15.0/go.mod 
h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
@@ -1072,8 +1072,8 @@
 golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod 
h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod 
h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.1.2/go.mod 
h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
-golang.org/x/tools v0.42.0/go.mod 
h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
+golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c=
+golang.org/x/tools v0.44.0/go.mod 
h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI=
 golang.org/x/tools/go/expect v0.1.1-deprecated 
h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
 golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod 
h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/backend/remote-state/azure/auth/oidc_auth.go 
new/opentofu-1.12.1/internal/backend/remote-state/azure/auth/oidc_auth.go
--- old/opentofu-1.12.0/internal/backend/remote-state/azure/auth/oidc_auth.go   
2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/backend/remote-state/azure/auth/oidc_auth.go   
2026-05-27 10:51:46.000000000 +0200
@@ -13,6 +13,7 @@
        "net/http"
 
        "github.com/Azure/azure-sdk-for-go/sdk/azcore"
+       "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
        "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
        "github.com/opentofu/opentofu/internal/httpclient"
        "github.com/opentofu/opentofu/internal/tfdiags"
@@ -53,9 +54,9 @@
                // a fresh OIDC token as needed, enabling proper token refresh 
behavior.
                func(ctx context.Context) (string, error) {
                        client := httpclient.New(ctx)
-                       
+
                        if config.OIDCToken == "" && config.OIDCTokenFilePath 
== "" {
-                               return getTokenFromRemote(client, 
config.OIDCAuthConfig)
+                               return getTokenFromRemote(client, 
config.OIDCAuthConfig, config.CloudConfig)
                        }
                        return consolidateToken(config)
                },
@@ -69,7 +70,7 @@
        Value string `json:"value"`
 }
 
-func getTokenFromRemote(client *http.Client, config OIDCAuthConfig) (string, 
error) {
+func getTokenFromRemote(client *http.Client, config OIDCAuthConfig, env 
cloud.Configuration) (string, error) {
        // GET from the request URL, using the bearer token
        req, err := http.NewRequest(http.MethodGet, config.OIDCRequestURL, nil)
        if err != nil {
@@ -79,9 +80,11 @@
        req.Header.Add("Accept", "application/json; api-version=2.0")
        req.Header.Add("Content-Type", "application/json")
 
-       query := req.URL.Query()
-       query.Set("audience", "api://AzureADTokenExchange")
-       req.URL.RawQuery = query.Encode()
+       if !req.URL.Query().Has("audience") {
+               query := req.URL.Query()
+               query.Set("audience", requestURLAudience(env))
+               req.URL.RawQuery = query.Encode()
+       }
 
        // Read the response
        resp, err := client.Do(req)
@@ -105,6 +108,22 @@
        return token.Value, nil
 }
 
+// requestURLAudience ensures the audience is configured appropriately for
+// its target cloud authority
+//
+// Reference:
+// 
https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-config-app-trust-managed-identity
+func requestURLAudience(env cloud.Configuration) string {
+       switch env.ActiveDirectoryAuthorityHost {
+       case "https://login.chinacloudapi.cn/":
+               return "api://AzureADTokenExchangeChina"
+       case "https://login.microsoftonline.us/":
+               return "api://AzureADTokenExchangeUSGov"
+       default:
+               return "api://AzureADTokenExchange"
+       }
+}
+
 func consolidateToken(config *Config) (string, error) {
        return consolidateFileAndValue(config.OIDCToken, 
config.OIDCTokenFilePath, "token", true)
 }
@@ -145,7 +164,7 @@
        }
        if directTokenUnset {
                // check request URL and token
-               _, err := getTokenFromRemote(httpclient.New(ctx), 
config.OIDCAuthConfig)
+               _, err := getTokenFromRemote(httpclient.New(ctx), 
config.OIDCAuthConfig, config.CloudConfig)
                if err != nil {
                        diags = diags.Append(tfdiags.Sourceless(
                                tfdiags.Error,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/internal/command/meta_providers.go 
new/opentofu-1.12.1/internal/command/meta_providers.go
--- old/opentofu-1.12.0/internal/command/meta_providers.go      2026-05-14 
11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/command/meta_providers.go      2026-05-27 
10:51:46.000000000 +0200
@@ -307,6 +307,11 @@
                checkedProvider := false
                var checkErr error
 
+               // This should only ever be called once per provider type.
+               // It creates the schema cache to be re-used in all of the 
subsequent
+               // provider instances.
+               factory := providerFactory(cached)
+
                factories[provider] = func() (providers.Interface, error) {
                        checkLock.Lock()
                        if !checkedProvider {
@@ -319,7 +324,7 @@
                                return nil, checkErr
                        }
 
-                       return providerFactory(cached)()
+                       return factory()
                }
        }
        for provider, localDir := range devOverrideProviders {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/encryption/keyprovider/azure_vault/config.go 
new/opentofu-1.12.1/internal/encryption/keyprovider/azure_vault/config.go
--- old/opentofu-1.12.0/internal/encryption/keyprovider/azure_vault/config.go   
2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/encryption/keyprovider/azure_vault/config.go   
2026-05-27 10:51:46.000000000 +0200
@@ -130,8 +130,8 @@
                return nil, nil, &keyprovider.ErrInvalidConfiguration{Message: 
"key_length must be at least 1"}
        }
 
-       environment := stringAttrDefaultEnvFallback(c.OIDCToken, "public", 
"ARM_ENVIRONMENT")
-       metadataHost := stringAttrEnvFallback(c.OIDCToken, "ARM_METADATA_HOST")
+       environment := stringAttrDefaultEnvFallback(c.Environment, "public", 
"ARM_ENVIRONMENT")
+       metadataHost := stringAttrEnvFallback(c.MetadataHost, 
"ARM_METADATA_HOST")
 
        cloudConfig, _, err := auth.CloudConfigFromAddresses(
                ctx,
@@ -176,8 +176,8 @@
                },
                StorageAddresses: auth.StorageAddresses{
                        CloudConfig:    cloudConfig,
-                       SubscriptionID: stringAttrEnvFallback(c.OIDCToken, 
"ARM_SUBSCRIPTION_ID"),
-                       TenantID:       stringAttrEnvFallback(c.OIDCToken, 
"ARM_TENANT_ID"),
+                       SubscriptionID: stringAttrEnvFallback(c.SubscriptionID, 
"ARM_SUBSCRIPTION_ID"),
+                       TenantID:       stringAttrEnvFallback(c.TenantID, 
"ARM_TENANT_ID"),
                },
                WorkloadIdentityAuthConfig: auth.WorkloadIdentityAuthConfig{
                        UseAKSWorkloadIdentity: c.UseAKS,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/encryption/keyprovider/azure_vault/config_test.go 
new/opentofu-1.12.1/internal/encryption/keyprovider/azure_vault/config_test.go
--- 
old/opentofu-1.12.0/internal/encryption/keyprovider/azure_vault/config_test.go  
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/opentofu-1.12.1/internal/encryption/keyprovider/azure_vault/config_test.go  
    2026-05-27 10:51:46.000000000 +0200
@@ -0,0 +1,122 @@
+// Copyright (c) The OpenTofu Authors
+// SPDX-License-Identifier: MPL-2.0
+// Copyright (c) 2023 HashiCorp, Inc.
+// SPDX-License-Identifier: MPL-2.0
+
+package azure_vault
+
+import (
+       "context"
+       "testing"
+
+       "github.com/hashicorp/hcl/v2"
+       "github.com/hashicorp/hcl/v2/gohcl"
+       "github.com/hashicorp/hcl/v2/hclsyntax"
+
+       "github.com/google/go-cmp/cmp"
+       "github.com/opentofu/opentofu/internal/backend/remote-state/azure/auth"
+)
+
+func getParsedConfig(c **auth.Config) authMethodGetter {
+       return func(ctx context.Context, authConfig *auth.Config) 
(auth.AuthMethod, error) {
+               *c = authConfig
+               return auth.GetAuthMethod(ctx, authConfig)
+       }
+}
+
+// This does not test the validity of the configuration.
+// It only checks that configuration variables passed in the key_provider 
block are recognized and used
+func TestConfig_Build(t *testing.T) {
+       cloudConfig, _, err := auth.CloudConfigFromAddresses(t.Context(), 
"public", "")
+       if err != nil {
+               t.Fatal(err)
+       }
+       testCases := map[string]struct {
+               input    string
+               expected *auth.Config
+       }{
+               "AuthConfigurationVariables": {
+                       input: `
+                               use_cli = false
+                               vault_uri = 
"https://example-keys.vault.azure.net";
+                               vault_key_name = "my-rsa-key"
+                               key_length = 32
+                               subscription_id = 
"xxxxxxxx-xxxx-xxxx-xxxx-subscriptionID"
+                               tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-tenantID"
+                               client_id = "xxxxxxxx-xxxx-xxxx-xxxx-clientID"
+                               client_id_file_path = "./client-id-file-path"
+                               client_secret = "client-secret-string"
+                               client_secret_file_path = 
"./client-secret-file-path"
+                               client_certificate = "client-certificate-string"
+                               client_certificate_password = 
"client-certificate-password"
+                               client_certificate_path = 
"./client-certificate-path"
+                               use_oidc = false
+                               oidc_token = "oidc_token"
+                               oidc_token_file_path = "./oidc-token-file-path"
+                               oidc_request_url = "https://oidc-request-url";
+                               oidc_request_token = "oidc-request-token"
+                               use_msi = false
+                               msi_endpoint = "https://msi-endpoint";
+                               use_aks_workload_identity = false
+                               `,
+                       expected: &auth.Config{
+                               AzureCLIAuthConfig: auth.AzureCLIAuthConfig{
+                                       CLIAuthEnabled: false,
+                               },
+                               ClientSecretCredentialAuthConfig: 
auth.ClientSecretCredentialAuthConfig{
+                                       ClientID:             
"xxxxxxxx-xxxx-xxxx-xxxx-clientID",
+                                       ClientIDFilePath:     
"./client-id-file-path",
+                                       ClientSecret:         
"client-secret-string",
+                                       ClientSecretFilePath: 
"./client-secret-file-path",
+                               },
+                               ClientCertificateAuthConfig: 
auth.ClientCertificateAuthConfig{
+                                       ClientCertificate:         
"client-certificate-string",
+                                       ClientCertificatePassword: 
"client-certificate-password",
+                                       ClientCertificatePath:     
"./client-certificate-path",
+                               },
+                               OIDCAuthConfig: auth.OIDCAuthConfig{
+                                       UseOIDC:           false,
+                                       OIDCToken:         "oidc_token",
+                                       OIDCTokenFilePath: 
"./oidc-token-file-path",
+                                       OIDCRequestURL:    
"https://oidc-request-url";,
+                                       OIDCRequestToken:  "oidc-request-token",
+                               },
+                               MSIAuthConfig: auth.MSIAuthConfig{
+                                       UseMsi:   false,
+                                       Endpoint: "https://msi-endpoint";,
+                               },
+                               StorageAddresses: auth.StorageAddresses{
+                                       CloudConfig:    cloudConfig,
+                                       SubscriptionID: 
"xxxxxxxx-xxxx-xxxx-xxxx-subscriptionID",
+                                       TenantID:       
"xxxxxxxx-xxxx-xxxx-xxxx-tenantID",
+                               },
+                               WorkloadIdentityAuthConfig: 
auth.WorkloadIdentityAuthConfig{
+                                       UseAKSWorkloadIdentity: false,
+                               },
+                       },
+               },
+       }
+       for name, testCase := range testCases {
+               t.Run(name, func(t *testing.T) {
+                       input, diags := 
hclsyntax.ParseConfig([]byte(testCase.input), "test_config", hcl.InitialPos)
+                       if diags.HasErrors() {
+                               t.Fatal(diags.Error())
+                       }
+                       config := new(Config)
+                       diags = gohcl.DecodeBody(input.Body, nil, config)
+                       if diags.HasErrors() {
+                               t.Fatal(diags.Error())
+                       }
+                       var authConfig *auth.Config
+                       getAuthMethod = getParsedConfig(&authConfig)
+                       _, _, err := config.Build()
+                       if authConfig == nil && err != nil {
+                               t.Fatal(err)
+                       }
+
+                       if diff := cmp.Diff(testCase.expected, authConfig); 
diff != "" {
+                               t.Errorf("mismatch (-expected +received):\n%s", 
diff)
+                       }
+               })
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/tofu/context_validate_test.go 
new/opentofu-1.12.1/internal/tofu/context_validate_test.go
--- old/opentofu-1.12.0/internal/tofu/context_validate_test.go  2026-05-14 
11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/tofu/context_validate_test.go  2026-05-27 
10:51:46.000000000 +0200
@@ -2969,3 +2969,209 @@
                })
        }
 }
+
+// Test that replace_triggered_by validates attribute traversals against the
+// schema of the referenced resource type, not the schema of the resource
+// containing the lifecycle block.
+func TestContext2Validate_replaceTriggeredByCrossResourceType(t *testing.T) {
+       // "test_instance" has a "value" attribute; "test_resource" does not.
+       // "test_resource" has a "output" attribute; "test_instance" does not.
+       p := testProvider("test")
+       p.GetProviderSchemaResponse = 
getProviderSchemaResponseFromProviderSchema(&ProviderSchema{
+               ResourceTypes: map[string]*configschema.Block{
+                       "test_instance": {
+                               Attributes: map[string]*configschema.Attribute{
+                                       "id":    {Type: cty.String, Computed: 
true},
+                                       "value": {Type: cty.String, Optional: 
true},
+                               },
+                       },
+                       "test_resource": {
+                               Attributes: map[string]*configschema.Attribute{
+                                       "id":     {Type: cty.String, Computed: 
true},
+                                       "output": {Type: cty.String, Computed: 
true},
+                               },
+                       },
+               },
+       })
+       p2 := testProvider("test2")
+       p2.GetProviderSchemaResponse = 
getProviderSchemaResponseFromProviderSchema(&ProviderSchema{
+               ResourceTypes: map[string]*configschema.Block{
+                       "test_instance": {
+                               Attributes: map[string]*configschema.Attribute{
+                                       "id":     {Type: cty.String, Computed: 
true},
+                                       "value2": {Type: cty.String, Optional: 
true},
+                               },
+                       },
+                       "test_resource": {
+                               Attributes: map[string]*configschema.Attribute{
+                                       "id":      {Type: cty.String, Computed: 
true},
+                                       "output2": {Type: cty.String, Computed: 
true},
+                               },
+                       },
+               },
+       })
+
+       tests := map[string]struct {
+               config    string
+               wantError bool
+       }{
+               "valid attribute reference on different resource type": {
+                       config: `
+resource "test_instance" "a" {
+  value = "hello"
+}
+
+resource "test_resource" "b" {
+  lifecycle {
+    replace_triggered_by = [test_instance.a.value]
+  }
+}
+`,
+                       wantError: false,
+               },
+               "valid attribute reference on different resource type 
configured with a different provider": {
+                       config: `
+resource "test_instance" "a" {
+  provider = test2
+  value2 = "hello"
+}
+resource "test_resource" "b" {
+  provider = test
+  lifecycle {
+    replace_triggered_by = [test_instance.a.value2]
+  }
+}
+`,
+                       wantError: false,
+               },
+               "valid attribute reference on different resource type 
configured with a different provider and count": {
+                       config: `
+resource "test_instance" "a" {
+  count = 2
+  provider = test2
+  value2 = "hello"
+}
+resource "test_resource" "b" {
+  provider = test
+  lifecycle {
+    replace_triggered_by = [test_instance.a[0].value2]
+  }
+}
+`,
+                       wantError: false,
+               },
+               "valid attribute reference on different resource type 
configured with a different provider and for_each": {
+                       config: `
+resource "test_instance" "a" {
+  for_each = toset(["a", "b"])
+  provider = test2
+  value2 = "hello"
+}
+resource "test_resource" "b" {
+  provider = test
+  lifecycle {
+    replace_triggered_by = [test_instance.a["b"].value2]
+  }
+}
+`,
+                       wantError: false,
+               },
+
+               "valid computed attribute reference on different resource 
type": {
+                       config: `
+resource "test_resource" "a" {}
+
+resource "test_instance" "b" {
+  lifecycle {
+    replace_triggered_by = [test_resource.a.output]
+  }
+}
+`,
+                       wantError: false,
+               },
+
+               "valid computed attribute references on multiple resources with 
the same type": {
+                       config: `
+resource "test_resource" "a" {}
+resource "test_resource" "b" {}
+resource "test_resource" "c" {}
+resource "test_instance" "d" {}
+
+resource "test_instance" "b" {
+  lifecycle {
+    replace_triggered_by = [
+      test_resource.a.output,
+      test_resource.b.output,
+      test_resource.c.output,
+      test_instance.d.value
+    ]
+  }
+}
+`,
+                       wantError: false,
+               },
+               "invalid attribute reference on different resource type": {
+                       config: `
+resource "test_instance" "a" {
+  value = "hello"
+}
+
+resource "test_resource" "b" {
+  lifecycle {
+    replace_triggered_by = [test_instance.a.nonexistent]
+  }
+}
+`,
+                       wantError: true,
+               },
+               "attribute exists on containing resource type but not 
referenced resource type": {
+                       config: `
+resource "test_instance" "a" {
+  value = "hello"
+}
+
+resource "test_resource" "b" {
+  lifecycle {
+    replace_triggered_by = [test_instance.a.output]
+  }
+}
+`,
+                       wantError: true,
+               },
+               "missing resource referenced in replace_triggered_by": {
+                       config: `
+resource "test_instance" "a" {
+  lifecycle {
+    replace_triggered_by = [
+      test_resource.missing.output,
+    ]
+  }
+}
+`,
+                       wantError: true,
+               },
+       }
+
+       for name, tc := range tests {
+               t.Run(name, func(t *testing.T) {
+                       m := testModuleInline(t, map[string]string{
+                               "main.tf": tc.config,
+                       })
+
+                       c := testContext2(t, &ContextOpts{
+                               Plugins: 
plugins.NewLibrary(map[addrs.Provider]providers.Factory{
+                                       addrs.NewDefaultProvider("test"):  
testProviderFuncFixed(p),
+                                       addrs.NewDefaultProvider("test2"): 
testProviderFuncFixed(p2),
+                               }, nil),
+                       })
+
+                       diags := c.Validate(context.Background(), m)
+                       if tc.wantError && !diags.HasErrors() {
+                               t.Fatal("succeeded; want error")
+                       }
+                       if !tc.wantError && diags.HasErrors() {
+                               t.Fatalf("unexpected error: %s", diags.Err())
+                       }
+               })
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/internal/tofu/node_provider.go 
new/opentofu-1.12.1/internal/tofu/node_provider.go
--- old/opentofu-1.12.0/internal/tofu/node_provider.go  2026-05-14 
11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/tofu/node_provider.go  2026-05-27 
10:51:46.000000000 +0200
@@ -103,9 +103,11 @@
        if op == walkValidate {
                log.Printf("[TRACE] NodeApplyableProvider: validating 
configuration for %s", n.Addr)
                instance, newDiags := evalCtx.Providers().NewProvider(ctx, 
n.Addr.Provider)
-               n.instances[addrs.NoKey] = instance
-               for key, data := range instanceData {
-                       diags = diags.Append(n.ValidateProvider(ctx, evalCtx, 
instance, key, data))
+               if !newDiags.HasErrors() { // We can't validate if we didn't 
successfully start the provider plugin
+                       n.instances[addrs.NoKey] = instance
+                       for key, data := range instanceData {
+                               diags = diags.Append(n.ValidateProvider(ctx, 
evalCtx, instance, key, data))
+                       }
                }
                return diags.Append(newDiags)
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/tofu/node_resource_abstract.go 
new/opentofu-1.12.1/internal/tofu/node_resource_abstract.go
--- old/opentofu-1.12.0/internal/tofu/node_resource_abstract.go 2026-05-14 
11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/tofu/node_resource_abstract.go 2026-05-27 
10:51:46.000000000 +0200
@@ -85,6 +85,8 @@
 
        ProvisionerSchemas map[string]*configschema.Block
 
+       ReplaceTriggeredBySchemas map[addrs.Resource]*configschema.Block
+
        // Set from GraphNodeTargetable
        Targets []addrs.Targetable
 
@@ -117,18 +119,19 @@
 }
 
 var (
-       _ GraphNodeReferenceable             = (*NodeAbstractResource)(nil)
-       _ GraphNodeReferencer                = (*NodeAbstractResource)(nil)
-       _ GraphNodeProviderConsumer          = (*NodeAbstractResource)(nil)
-       _ GraphNodeProvisionerConsumer       = (*NodeAbstractResource)(nil)
-       _ GraphNodeConfigResource            = (*NodeAbstractResource)(nil)
-       _ GraphNodeAttachResourceConfig      = (*NodeAbstractResource)(nil)
-       _ GraphNodeAttachResourceSchema      = (*NodeAbstractResource)(nil)
-       _ GraphNodeAttachProvisionerSchema   = (*NodeAbstractResource)(nil)
-       _ GraphNodeAttachProviderMetaConfigs = (*NodeAbstractResource)(nil)
-       _ GraphNodeTargetable                = (*NodeAbstractResource)(nil)
-       _ graphNodeAttachResourceDependsOn   = (*NodeAbstractResource)(nil)
-       _ dag.GraphNodeDotter                = (*NodeAbstractResource)(nil)
+       _ GraphNodeReferenceable                  = (*NodeAbstractResource)(nil)
+       _ GraphNodeReferencer                     = (*NodeAbstractResource)(nil)
+       _ GraphNodeProviderConsumer               = (*NodeAbstractResource)(nil)
+       _ GraphNodeProvisionerConsumer            = (*NodeAbstractResource)(nil)
+       _ GraphNodeConfigResource                 = (*NodeAbstractResource)(nil)
+       _ GraphNodeAttachResourceConfig           = (*NodeAbstractResource)(nil)
+       _ GraphNodeAttachResourceSchema           = (*NodeAbstractResource)(nil)
+       _ GraphNodeAttachReplaceTriggeredBySchema = (*NodeAbstractResource)(nil)
+       _ GraphNodeAttachProvisionerSchema        = (*NodeAbstractResource)(nil)
+       _ GraphNodeAttachProviderMetaConfigs      = (*NodeAbstractResource)(nil)
+       _ GraphNodeTargetable                     = (*NodeAbstractResource)(nil)
+       _ graphNodeAttachResourceDependsOn        = (*NodeAbstractResource)(nil)
+       _ dag.GraphNodeDotter                     = (*NodeAbstractResource)(nil)
 )
 
 // NewNodeAbstractResource creates an abstract resource graph node for
@@ -470,6 +473,29 @@
        n.ProvisionerSchemas[name] = schema
 }
 
+// GraphNodeAttachReplaceTriggeredBySchema
+func (n *NodeAbstractResource) ReplaceTriggeredBy() []*addrs.Reference {
+       // If we have no configuration, then we have no replace_triggred_by
+       if n.Config == nil || len(n.Config.TriggersReplacement) == 0 {
+               return nil
+       }
+       result := make([]*addrs.Reference, 0, len(n.Config.TriggersReplacement))
+       for _, expr := range n.Config.TriggersReplacement {
+               refs, _ := lang.ReferencesInExpr(addrs.ParseRef, expr)
+               result = append(result, refs...)
+       }
+
+       return result
+}
+
+// GraphNodeAttachReplaceTriggeredBySchema
+func (n *NodeAbstractResource) AttachReplaceTriggeredBySchema(addr 
addrs.Resource, schema *configschema.Block) {
+       if n.ReplaceTriggeredBySchemas == nil {
+               n.ReplaceTriggeredBySchemas = 
make(map[addrs.Resource]*configschema.Block)
+       }
+       n.ReplaceTriggeredBySchemas[addr] = schema
+}
+
 // GraphNodeResource
 func (n *NodeAbstractResource) ResourceAddr() addrs.ConfigResource {
        return n.Addr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/tofu/node_resource_validate.go 
new/opentofu-1.12.1/internal/tofu/node_resource_validate.go
--- old/opentofu-1.12.0/internal/tofu/node_resource_validate.go 2026-05-14 
11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/tofu/node_resource_validate.go 2026-05-27 
10:51:46.000000000 +0200
@@ -360,15 +360,34 @@
                                        continue
                                }
 
-                               if len(ref.Remaining) == 0 {
+                               var refAddr addrs.Resource
+                               switch rs := ref.Subject.(type) {
+                               case addrs.Resource:
+                                       refAddr = rs
+                               case addrs.ResourceInstance:
+                                       refAddr = rs.Resource
+                               default:
                                        continue
                                }
 
-                               // Validate if rest of the reference is valid. 
The check above does not do that,
-                               // it only checks the resource type and its 
primary attributes.
-                               remainingDiags := 
schemaForType.Block.StaticValidateTraversal(ref.Remaining)
-                               if remainingDiags.HasErrors() {
-                                       diags = diags.Append(remainingDiags)
+                               refSchema, ok := 
n.ReplaceTriggeredBySchemas[refAddr]
+                               if !ok {
+                                       // (We could also get here if 
[AttachSchemaTransformer] has a bug that
+                                       // makes it fail to register one of the 
needed schemas.)
+                                       diags = diags.Append(&hcl.Diagnostic{
+                                               Severity: hcl.DiagError,
+                                               Summary:  "Undeclared resource 
in replace_triggered_by",
+                                               Detail:   fmt.Sprintf("Resource 
%s refers to %s in replace_triggered_by, but it is not declared in this 
module.", n.Addr, refAddr),
+                                               Subject:  expr.Range().Ptr(),
+                                       })
+                                       continue
+                               }
+
+                               if len(ref.Remaining) != 0 {
+                                       remainingDiags := 
refSchema.StaticValidateTraversal(ref.Remaining)
+                                       if remainingDiags.HasErrors() {
+                                               diags = 
diags.Append(remainingDiags)
+                                       }
                                }
                        }
                }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.12.0/internal/tofu/transform_attach_schema.go 
new/opentofu-1.12.1/internal/tofu/transform_attach_schema.go
--- old/opentofu-1.12.0/internal/tofu/transform_attach_schema.go        
2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/internal/tofu/transform_attach_schema.go        
2026-05-27 10:51:46.000000000 +0200
@@ -38,13 +38,26 @@
 type GraphNodeAttachProvisionerSchema interface {
        ProvisionedBy() []string
 
-       // SetProvisionerSchema is called during transform for each provisioner
+       // AttachProvisionerSchema is called during transform for each 
provisioner
        // type returned from ProvisionedBy, providing the configuration schema
        // for each provisioner in turn. The implementer should save these for
        // later use in evaluating provisioner configuration blocks.
        AttachProvisionerSchema(name string, schema *configschema.Block)
 }
 
+// GraphNodeAttachReplaceTriggeredBySchema is an interface implemented by node 
types
+// that need one or more provider schemas attached for the 
replace_triggered_by.
+type GraphNodeAttachReplaceTriggeredBySchema interface {
+       GraphNodeConfigResource
+       ReplaceTriggeredBy() []*addrs.Reference
+
+       // AttachReplaceTriggeredBySchema is called during transform for each 
resource type
+       // type returned from ReplaceTriggeredBy, providing the configuration 
schema
+       // for each referenced provider in turn. The implementer should save 
these for
+       // later use in evaluating replace_triggered_by references.
+       AttachReplaceTriggeredBySchema(ref addrs.Resource, schema 
*configschema.Block)
+}
+
 // AttachSchemaTransformer finds nodes that implement
 // GraphNodeAttachResourceSchema, GraphNodeAttachProviderConfigSchema, or
 // GraphNodeAttachProvisionerSchema, looks up the needed schemas for each
@@ -61,6 +74,8 @@
                return fmt.Errorf("AttachSchemaTransformer used with nil 
Plugins")
        }
 
+       refMap := addrs.MakeMap[addrs.ConfigResource, *configschema.Block]()
+
        for _, v := range g.Vertices() {
 
                if tv, ok := v.(GraphNodeAttachResourceSchema); ok {
@@ -80,6 +95,8 @@
                        }
                        log.Printf("[TRACE] AttachSchemaTransformer: attaching 
resource schema to %s", dag.VertexName(v))
                        tv.AttachResourceSchema(schema, version)
+
+                       refMap.Put(addr, schema)
                }
 
                if tv, ok := v.(GraphNodeAttachProviderConfigSchema); ok {
@@ -113,6 +130,31 @@
                        }
                }
        }
+
+       for _, v := range g.Vertices() {
+               if tv, ok := v.(GraphNodeAttachReplaceTriggeredBySchema); ok {
+                       module := tv.ResourceAddr().Module
+                       refs := tv.ReplaceTriggeredBy()
+                       for _, ref := range refs {
+                               var refAddr addrs.ConfigResource
+                               switch rs := ref.Subject.(type) {
+                               case addrs.Resource:
+                                       refAddr = rs.InModule(module)
+                               case addrs.ResourceInstance:
+                                       refAddr = rs.Resource.InModule(module)
+                               default:
+                                       continue
+                               }
+                               schema, ok := refMap.GetOk(refAddr)
+                               if ok {
+                                       log.Printf("[TRACE] 
AttachSchemaTransformer: attaching replace_triggered_by %q config schema to 
%s", refAddr, dag.VertexName(v))
+                                       
tv.AttachReplaceTriggeredBySchema(refAddr.Resource, schema)
+                               } else {
+                                       log.Printf("[WARN] 
AttachSchemaTransformer: missing replace_triggered_by %q in %s", refAddr, 
dag.VertexName(v))
+                               }
+                       }
+               }
+       }
 
        return nil
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.12.0/version/VERSION 
new/opentofu-1.12.1/version/VERSION
--- old/opentofu-1.12.0/version/VERSION 2026-05-14 11:57:57.000000000 +0200
+++ new/opentofu-1.12.1/version/VERSION 2026-05-27 10:51:46.000000000 +0200
@@ -1 +1 @@
-1.12.0
+1.12.1

++++++ opentofu.obsinfo ++++++
--- /var/tmp/diff_new_pack.J8wOX5/_old  2026-05-29 18:10:29.226811216 +0200
+++ /var/tmp/diff_new_pack.J8wOX5/_new  2026-05-29 18:10:29.274813282 +0200
@@ -1,5 +1,5 @@
 name: opentofu
-version: 1.12.0
-mtime: 1778752677
-commit: bdcbf091aab886499ed7718d7f558b428fffce39
+version: 1.12.1
+mtime: 1779871906
+commit: dc29882638869cdc60f871a112a04a415042caf1
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/opentofu/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.opentofu.new.1937/vendor.tar.gz differ: char 13, 
line 1

Reply via email to