Repository: confluentinc/terraform-provider-confluent
Pull request #654: [RCCA-23805] Cannot remove `ruleSet` via terraform resource `confluent_schema`
Author: login: tmalikconfluent
Created: 2025-04-18T22:04:10Z | Merged: 2025-05-20T17:35:07Z

Release Notes
---------
<!-- If this PR introduces any user-facing changes, document them below as a summary. Delete unused section titles and placeholders. Match the style of previous release notes: https://github.com/confluentinc/terraform-provider-confluent/releases -->

New Features
- [Briefly describe new features introduced in this PR].

Bug Fixes
- [Briefly describe any bugs fixed in this PR].

Examples
- [Briefly describe any Terraform configuration example updates in this PR].

Checklist
---------
<!-- 
Check each item in the checklist to ensure high-quality Terraform development practices are followed. PR approval won't be granted until the checklist is carefully reviewed.
For instructions, please refer to this Confluence page: https://confluentinc.atlassian.net/wiki/spaces/AEGI/pages/3938058831/
-->
- [x] I can successfully build and use a custom Terraform provider binary for Confluent.
- [x] I have verified my PR with real Confluent Cloud resources in a pre-prod or production environment, or both.
- [x] I have attached manual Terraform verification results or screenshots in the `Test & Review` section below.
- [x] I have included appropriate Terraform acceptance or unit tests for any new resource, data source, or functionality.
- [x] I confirm that this PR introduces no breaking changes or backward compatibility issues.
- [x] I have updated the corresponding documentation and include relevant examples for this PR.
- [x] I have indicated the potential customer impact if something goes wrong in the `Blast Radius` section below.
- [x] I have put checkmarks below confirming that the feature associated with this PR is enabled in:
  - [x] Confluent Cloud prod
  - [ ] Confluent Cloud stag
  - [ ] Check this box if the feature is enabled for certain organizations only

What
----
Allow deletion of rulesets in schemas using terraform for advacned package users
<!--
Briefly describe **what** you have changed and **why** these changes are necessary.
Optionally include: 
- The problem being solved or the feature being added. 
- The implementation strategy or approach taken. 
- Key technical details, design decisions, or any additional context reviewers should be aware of.
-->

Blast Radius
----
All customers using schemas.
<!--
The Blast Radius section should include information on what will be the customer(s) impact if something goes wrong or unexpectedly, 
adding this section will trigger the PR author to think about the impact from product perspective, examples can be:
- Confluent Cloud customers who are using `confluent_kafka_cluster` resource/data-source will be blocked.
- Confluent Cloud customers who are using `confluent_schema` resource for schema validation will be blocked.
- All customers who are using `terraform import` function for resources will be impacted.
-->

References
----------
https://confluentinc.atlassian.net/browse/RCCA-23805
<!-- Include links to relevant resources for this PR, such as: 
- Related GitHub issues 
- Tickets (JIRA, etc.) 
- Internal documentation or design specs 
- Other related PRs 
Copy and paste the links below for easy reference.
-->

Test & Review
-------------
Testing doc: https://docs.google.com/document/d/1hlbKjbFxHq1P7ZjenO2gjZXcFFJyixSBMCwbZauJ8P0/edit?tab=t.0
Testing doc 2: https://docs.google.com/document/d/1BcLmJWdvj0BF5FcbLlbTaIHDTrPb0PUi9DjSORci1K8/edit?tab=t.0
<!-- Has this PR been tested? If so, explain **how** it was tested. Include: 
- Steps taken to verify the changes. 
- Links to manual verification documents, logs, or screenshots to save reviewers' time. 
- Any additional notes on testing (e.g., environments used, edge cases tested). 
- Screenshot showing successful resource creation.
Example: - [Manual Verification Document](https://docs.google.com/document/d/1dutVZmbEwJBBqMzx57uCXqllV1SEr2vxnjUrtTPCwBk/edit?tab=t.0#heading=h.6zajc95mev5j)
-->



Diff:
diff --git a/docs/resources/confluent_schema.md b/docs/resources/confluent_schema.md
index 8b2efc76d..cfd9811c8 100644
--- a/docs/resources/confluent_schema.md
+++ b/docs/resources/confluent_schema.md
@@ -121,6 +121,8 @@ The following arguments are supported:
 
 -> **Note:** The Confluent Cloud Console uses the following default values: `on_success = "NONE"` and `on_failure = "ERROR"`. However, the TF Provider sets its defaults to `on_success = "NONE,NONE"` and `on_failure = "ERROR,ERROR"`.
 
+-> **Note:** To delete all domain rules from an existing schema, remove the `ruleset` block from the `confluent_schema` resource in the Terraform configuration.
+
 ## Attributes Reference
 
 In addition to the preceding arguments, the following attributes are exported:
diff --git a/internal/provider/resource_schema.go b/internal/provider/resource_schema.go
index c93101ba0..624e745a3 100644
--- a/internal/provider/resource_schema.go
+++ b/internal/provider/resource_schema.go
@@ -189,7 +189,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
-		Computed: true,
+		Computed: false,
 		Optional: true,
 	}
 }
@@ -352,13 +352,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset. // TODO: Revisit this logic after we add migration rules, this might never be hit.
+			ruleset := sr.NewRuleSet()
+			ruleset.SetDomainRules([]sr.Rule{})
+			createSchemaRequest.SetRuleSet(*ruleset)
+		} else { //this is the case when a ruleset is not empty after an operation.
+			ruleset := sr.NewRuleSet()
+			tfRulesetMap := tfRuleset[0].(map[string]interface{})
+			if tfRulesetMap[paramDomainRules] != nil {
+				ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+			}
+			createSchemaRequest.SetRuleSet(*ruleset)
 		}
-		createSchemaRequest.SetRuleSet(*ruleset)
 	}
 	if tfMetadata := diff.Get(paramMetadata).([]interface{}); len(tfMetadata) == 1 {
 		metadata := sr.NewMetadata()
@@ -564,7 +571,12 @@ func schemaCreate(ctx context.Context, d *schema.ResourceData, meta interface{})
 	createSchemaRequest.SetSchemaType(format)
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
-	if tfRuleset := d.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
+	oldRuleset, newRuleset := d.GetChange(paramRuleset)
+	if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset.
+		ruleset := sr.NewRuleSet()
+		ruleset.SetDomainRules([]sr.Rule{})
+		createSchemaRequest.SetRuleSet(*ruleset)
+	} else if tfRuleset := d.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 { //this is the case when a ruleset is not empty after an operation.
 		ruleset := sr.NewRuleSet()
 		tfRulesetMap := tfRuleset[0].(map[string]interface{})
 		if tfRulesetMap[paramDomainRules] != nil {
diff --git a/internal/provider/resource_schema_latest_refresh_test.go b/internal/provider/resource_schema_latest_refresh_test.go
index bf90ea6b9..348870c9a 100644
--- a/internal/provider/resource_schema_latest_refresh_test.go
+++ b/internal/provider/resource_schema_latest_refresh_test.go
@@ -267,6 +267,28 @@ func testAccCheckLatestRefreshSchemaConfig(confluentCloudBaseUrl, mockServerUrl
         subject_name = "%s"
         version = %d
       }
+  	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
 	}
 	`, confluentCloudBaseUrl, testSchemaResourceLabel, testStreamGovernanceClusterId, mockServerUrl, testSchemaRegistryKey, testSchemaRegistrySecret, testSubjectName, testFormat, schemaContent,
 		testHardDelete, testSkipSchemaValidationDuringPlanTrue,
diff --git a/internal/provider/resource_schema_latest_test.go b/internal/provider/resource_schema_latest_test.go
index 3b9f12bdd..d47f956b5 100644
--- a/internal/provider/resource_schema_latest_test.go
+++ b/internal/provider/resource_schema_latest_test.go
@@ -42,6 +42,37 @@ const (
       "version": 9
     }
   ],
+ "ruleSet" : {
+    "domainRules" : [ {   
+        "disabled" : false,                                                          
+        "doc" : "",
+        "expr" : "",
+        "kind" : "TRANSFORM",
+        "mode" : "WRITEREAD",
+        "name" : "encrypt",
+        "onFailure" : "ERROR,ERROR",
+        "onSuccess" : "NONE,NONE",
+        "params" : {
+            "encrypt.kek.name" : "testkek2"
+            },
+        "tags" : [ "PIIIII" ],
+        "type" : "ENCRYPT"
+        }, {
+        "disabled" : false,
+        "doc" : "",
+        "expr" : "",
+        "kind" : "TRANSFORM",
+        "mode" : "WRITEREAD",
+        "name" : "encryptPII",
+        "onFailure" : "ERROR,ERROR",
+        "onSuccess" : "NONE,NONE",
+        "params" : {
+            "encrypt.kek.name" : "testkek2"
+            },
+         "tags" : [ "PII" ],
+         "type" : "ENCRYPT"
+         } ]
+},
   "schema": "foobar",
   "schemaType": "AVRO"
 }`
@@ -314,6 +345,28 @@ func testAccCheckLatestSchemaConfig(confluentCloudBaseUrl, mockServerUrl string)
         subject_name = "%s"
         version = %d
       }
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
 
       schema_reference {
         name = "%s"
@@ -347,6 +400,28 @@ func testAccCheckLatestSchemaConfigWithUpdatedCredentials(confluentCloudBaseUrl,
 
       hard_delete = "%s"
       recreate_on_update = "%s"
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
 	  
       schema_reference {
         name = "%s"
diff --git a/internal/provider/resource_schema_ruleset_test.go b/internal/provider/resource_schema_ruleset_test.go
new file mode 100644
index 000000000..8d50a135c
--- /dev/null
+++ b/internal/provider/resource_schema_ruleset_test.go
@@ -0,0 +1,366 @@
+package provider
+
+import (
+	"context"
+	"fmt"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+	"github.com/walkerus/go-wiremock"
+	"io/ioutil"
+	"net/http"
+	"strconv"
+	"testing"
+)
+
+var scenarioStateSchemaHasBeenCreated2 = "A new schema has been just created 2"
+
+func TestAccRulesetSchema(t *testing.T) {
+	ctx := context.Background()
+
+	wiremockContainer, err := setupWiremock(ctx)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer wiremockContainer.Terminate(ctx)
+
+	mockSchemaTestServerUrl := wiremockContainer.URI
+	wiremockClient := wiremock.NewClient(mockSchemaTestServerUrl)
+	// nolint:errcheck
+	defer wiremockClient.Reset()
+	confluentCloudBaseUrl := ""
+	// nolint:errcheck
+	defer wiremockClient.ResetAllScenarios()
+
+	validateSchemaResponse, _ := ioutil.ReadFile("../testdata/schema_registry_schema/validate_schema.json")
+	validateSchemaStub := wiremock.Post(wiremock.URLPathEqualTo(validateSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(wiremock.ScenarioStateStarted).
+		WillReturn(
+			string(validateSchemaResponse),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		)
+	_ = wiremockClient.StubFor(validateSchemaStub)
+
+	createSchemaResponse, _ := ioutil.ReadFile("../testdata/schema_registry_schema/create_schema.json")
+	createSchemaStub := wiremock.Post(wiremock.URLPathEqualTo(createSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(wiremock.ScenarioStateStarted).
+		WillSetStateTo(scenarioStateSchemaHasBeenCreated).
+		WillReturn(
+			string(createSchemaResponse),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		)
+	_ = wiremockClient.StubFor(createSchemaStub)
+
+	readCreatedSchemasResponse, _ := ioutil.ReadFile("../testdata/schema_registry_schema/read_schemas.json")
+	_ = wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo(readSchemasPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated).
+		WillReturn(
+			string(readCreatedSchemasResponse),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		))
+
+	readLatestSchemaResponse, _ := ioutil.ReadFile("../testdata/schema_registry_schema/read_latest_schema.json")
+	_ = wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo(readLatestSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated).
+		WillReturn(
+			string(readLatestSchemaResponse),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		))
+
+	validateSchemaResponse2, _ := ioutil.ReadFile("../testdata/schema_registry_schema/validate_schema.json")
+	validateSchemaStub2 := wiremock.Post(wiremock.URLPathEqualTo(validateSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated).
+		WillReturn(
+			string(validateSchemaResponse2),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		)
+	_ = wiremockClient.StubFor(validateSchemaStub2)
+
+	createSchemaResponse2, _ := ioutil.ReadFile("../testdata/schema_registry_schema/create_schema.json")
+	createSchemaStub2 := wiremock.Post(wiremock.URLPathEqualTo(createSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated).
+		WillSetStateTo(scenarioStateSchemaHasBeenCreated2).
+		WillReturn(
+			string(createSchemaResponse2),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		)
+	_ = wiremockClient.StubFor(createSchemaStub2)
+
+	readCreatedSchemasResponse2, _ := ioutil.ReadFile("../testdata/schema_registry_schema/read_ruleset_delete.json")
+	_ = wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo(readSchemasPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated2).
+		WillReturn(
+			string(readCreatedSchemasResponse2),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		))
+
+	readLatestSchemaResponse2, _ := ioutil.ReadFile("../testdata/schema_registry_schema/read_ruleset_delete_latest.json")
+	_ = wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo(readLatestSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated2).
+		WillReturn(
+			string(readLatestSchemaResponse2),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		))
+
+	deleteSchemaStub := wiremock.Delete(wiremock.URLPathEqualTo(deleteSchemaPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenCreated2).
+		WillSetStateTo(scenarioStateSchemaHasBeenDeleted).
+		WillReturn(
+			"",
+			contentTypeJSONHeader,
+			http.StatusNoContent,
+		)
+	_ = wiremockClient.StubFor(deleteSchemaStub)
+
+	readDeletedSaResponse, _ := ioutil.ReadFile("../testdata/schema_registry_schema/read_schemas_after_delete.json")
+	_ = wiremockClient.StubFor(wiremock.Get(wiremock.URLPathEqualTo(readSchemasPath)).
+		InScenario(schemaScenarioName).
+		WhenScenarioStateIs(scenarioStateSchemaHasBeenDeleted).
+		WillReturn(
+			string(readDeletedSaResponse),
+			contentTypeJSONHeader,
+			http.StatusOK,
+		))
+	resource.Test(t, resource.TestCase{
+		PreCheck:          func() { testAccPreCheck(t) },
+		ProviderFactories: testAccProviderFactories,
+		CheckDestroy: func(s *terraform.State) error {
+			return testAccCheckSchemaDestroy(s, mockSchemaTestServerUrl)
+		},
+		// https://www.terraform.io/docs/extend/testing/acceptance-tests/teststep.html
+		// https://www.terraform.io/docs/extend/best-practices/testing.html#built-in-patterns
+		Steps: []resource.TestStep{
+			{
+				Config: testAccCheckRulesetSchemaConfig(confluentCloudBaseUrl, mockSchemaTestServerUrl),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckSchemaExists(fullSchemaResourceLabel),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "id", fmt.Sprintf("%s/%s/%s", testStreamGovernanceClusterId, testSubjectName, latestSchemaVersionAndPlaceholderForSchemaIdentifier)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.0.%", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.0.id", testStreamGovernanceClusterId),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "rest_endpoint", mockSchemaTestServerUrl),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.key", testSchemaRegistryKey),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.secret", testSchemaRegistrySecret),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "subject_name", testSubjectName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "format", testFormat),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema", testSchemaContent),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "version", strconv.Itoa(testSchemaVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_identifier", strconv.Itoa(testSchemaIdentifier)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "hard_delete", testHardDelete),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "recreate_on_update", testRecreateOnUpdateFalse),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "skip_validation_during_plan", testSkipSchemaValidationDuringPlanTrue),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.#", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.%", "3"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.name", testFirstSchemaReferenceDisplayName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.subject_name", testFirstSchemaReferenceSubject),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.version", strconv.Itoa(testFirstSchemaReferenceVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.%", "3"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.name", testSecondSchemaReferenceDisplayName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.subject_name", testSecondSchemaReferenceSubject),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.version", strconv.Itoa(testSecondSchemaReferenceVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "%", strconv.Itoa(testNumberOfSchemaRegistrySchemaResourceAttributes)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.#", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.%", "11"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.doc", ""),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.expr", ""),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.kind", "TRANSFORM"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.mode", "WRITEREAD"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.name", "encrypt"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_failure", "ERROR,ERROR"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_success", "NONE,NONE"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.params.%", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.params.encrypt.kek.name", "testkek2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.tags.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.tags.0", "PIIIII"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.type", "ENCRYPT"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.disabled", "false"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.%", "11"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.doc", ""),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.expr", ""),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.kind", "TRANSFORM"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.mode", "WRITEREAD"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.name", "encryptPII"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.on_failure", "ERROR,ERROR"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.on_success", "NONE,NONE"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.params.%", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.params.encrypt.kek.name", "testkek2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.tags.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.tags.0", "PII"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.type", "ENCRYPT"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.disabled", "false"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.%", "3"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.properties.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.properties.email", "bob@acme.com"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.properties.owner", "Bob Jones"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.sensitive.#", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.sensitive.0", "s1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.sensitive.1", "s2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.#", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.0.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.0.key", "tag1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.0.value.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.0.value.0", "PII"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.1.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.1.key", "tag2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.1.value.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "metadata.0.tags.1.value.0", "PIIIII"),
+				),
+			},
+			{
+				Config: testAccCheckRulesetSchemaConfigWithUpdatedCredentials(confluentCloudBaseUrl, mockSchemaTestServerUrl),
+				Check: resource.ComposeTestCheckFunc(
+					testAccCheckSchemaExists(fullSchemaResourceLabel),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "id", fmt.Sprintf("%s/%s/%s", testStreamGovernanceClusterId, testSubjectName, latestSchemaVersionAndPlaceholderForSchemaIdentifier)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.0.%", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_registry_cluster.0.id", testStreamGovernanceClusterId),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "rest_endpoint", mockSchemaTestServerUrl),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.#", "1"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.%", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.key", testSchemaRegistryKey),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "credentials.0.secret", testSchemaRegistrySecret),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "subject_name", testSubjectName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "format", testFormat),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema", testSchemaContent),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "version", strconv.Itoa(testSchemaVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_identifier", strconv.Itoa(testSchemaIdentifier)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "hard_delete", testHardDelete),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "recreate_on_update", testRecreateOnUpdateFalse),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "skip_validation_during_plan", testSkipSchemaValidationDuringPlanTrue),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.#", "2"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.%", "3"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.name", testFirstSchemaReferenceDisplayName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.subject_name", testFirstSchemaReferenceSubject),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.0.version", strconv.Itoa(testFirstSchemaReferenceVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.%", "3"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.name", testSecondSchemaReferenceDisplayName),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.subject_name", testSecondSchemaReferenceSubject),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "schema_reference.1.version", strconv.Itoa(testSecondSchemaReferenceVersion)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "%", strconv.Itoa(testNumberOfSchemaRegistrySchemaResourceAttributes)),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.#", "0"),
+				),
+			},
+		},
+	})
+}
+
+func testAccCheckRulesetSchemaConfig(confluentCloudBaseUrl, mockServerUrl string) string {
+	return fmt.Sprintf(`
+	provider "confluent" {
+      endpoint = "%s"
+    }
+	resource "confluent_schema" "%s" {
+	  schema_registry_cluster {
+        id = "%s"
+      }
+      rest_endpoint = "%s"
+      credentials {
+        key = "%s"
+        secret = "%s"
+	  }
+	
+	  subject_name = "%s"
+	  format = "%s"
+      schema = "%s"
+
+      hard_delete = "%s"
+      skip_validation_during_plan = "%s" 
+	  
+      schema_reference {
+        name = "%s"
+        subject_name = "%s"
+        version = %d
+      }
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
+
+      schema_reference {
+        name = "%s"
+        subject_name = "%s"
+        version = %d
+      }
+	}`, confluentCloudBaseUrl, testSchemaResourceLabel, testStreamGovernanceClusterId, mockServerUrl, testSchemaRegistryKey, testSchemaRegistrySecret, testSubjectName, testFormat, testSchemaContent,
+		testHardDelete, testSkipSchemaValidationDuringPlanTrue,
+		testFirstSchemaReferenceDisplayName, testFirstSchemaReferenceSubject, testFirstSchemaReferenceVersion,
+		testSecondSchemaReferenceDisplayName, testSecondSchemaReferenceSubject, testSecondSchemaReferenceVersion)
+}
+
+func testAccCheckRulesetSchemaConfigWithUpdatedCredentials(confluentCloudBaseUrl, mockServerUrl string) string {
+	return fmt.Sprintf(`
+	provider "confluent" {
+      endpoint = "%s"
+    }
+	resource "confluent_schema" "%s" {
+	  schema_registry_cluster {
+        id = "%s"
+      }
+      rest_endpoint = "%s"
+      credentials {
+        key = "%s"
+        secret = "%s"
+	  }
+	
+	  subject_name = "%s"
+	  format = "%s"
+      schema = "%s"
+
+      hard_delete = "%s"
+      skip_validation_during_plan = "%s" 
+	  
+      schema_reference {
+        name = "%s"
+        subject_name = "%s"
+        version = %d
+      }
+
+      schema_reference {
+        name = "%s"
+        subject_name = "%s"
+        version = %d
+      }
+	}`, confluentCloudBaseUrl, testSchemaResourceLabel, testStreamGovernanceClusterId, mockServerUrl, testSchemaRegistryKey, testSchemaRegistrySecret, testSubjectName, testFormat, testSchemaContent,
+		testHardDelete, testSkipSchemaValidationDuringPlanTrue,
+		testFirstSchemaReferenceDisplayName, testFirstSchemaReferenceSubject, testFirstSchemaReferenceVersion,
+		testSecondSchemaReferenceDisplayName, testSecondSchemaReferenceSubject, testSecondSchemaReferenceVersion)
+}
diff --git a/internal/provider/resource_schema_versioned_provider_block_test.go b/internal/provider/resource_schema_versioned_provider_block_test.go
index 64b4ffc68..2407c3b37 100644
--- a/internal/provider/resource_schema_versioned_provider_block_test.go
+++ b/internal/provider/resource_schema_versioned_provider_block_test.go
@@ -185,6 +185,29 @@ func testAccCheckVersionedSchemaConfigWithEnhancedProviderBlock(confluentCloudBa
         version = %d
       }
 
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
+
       schema_reference {
         name = "%s"
         subject_name = "%s"
diff --git a/internal/provider/resource_schema_versioned_test.go b/internal/provider/resource_schema_versioned_test.go
index 80e77866b..d515e0712 100644
--- a/internal/provider/resource_schema_versioned_test.go
+++ b/internal/provider/resource_schema_versioned_test.go
@@ -317,6 +317,28 @@ func testAccCheckSchemaConfig(confluentCloudBaseUrl, mockServerUrl string) strin
         subject_name = "%s"
         version = %d
       }
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
 	}
 	`, confluentCloudBaseUrl, testSchemaResourceLabel, testStreamGovernanceClusterId, mockServerUrl, testSchemaRegistryKey, testSchemaRegistrySecret, testSubjectName, testFormat, testSchemaContent,
 		testHardDelete, testRecreateOnUpdateTrue, testSkipSchemaValidationDuringPlanTrue,
@@ -357,6 +379,28 @@ func testAccCheckSchemaConfigWithUpdatedCredentials(confluentCloudBaseUrl, mockS
         subject_name = "%s"
         version = %d
       }
+	  ruleset {
+		domain_rules {
+		  name = "encryptPII"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+		domain_rules  {
+		  name = "encrypt"
+		  kind = "TRANSFORM"
+		  type = "ENCRYPT"
+		  mode = "WRITEREAD"
+		  tags = ["PIIIII"]
+		  params = {
+			  "encrypt.kek.name" = "testkek2"
+		  }
+		}
+	  }
 	}
 	`, confluentCloudBaseUrl, testSchemaResourceLabel, testStreamGovernanceClusterId, mockServerUrl, testSchemaRegistryUpdatedKey, testSchemaRegistryUpdatedSecret, testSubjectName, testFormat, testSchemaContent,
 		testHardDelete, testRecreateOnUpdateTrue, testSkipSchemaValidationDuringPlanFalse,
diff --git a/internal/testdata/schema_registry_schema/read_ruleset_delete.json b/internal/testdata/schema_registry_schema/read_ruleset_delete.json
new file mode 100644
index 000000000..dcadbfec4
--- /dev/null
+++ b/internal/testdata/schema_registry_schema/read_ruleset_delete.json
@@ -0,0 +1,38 @@
+[
+  {
+    "subject": "test2",
+    "version": 8,
+    "id": 100001,
+    "schema": "foobar",
+    "references": [
+      {
+        "name": "sampleRecord",
+        "subject": "test2",
+        "version": 9
+      },
+      {
+        "name": "sampleRecord2",
+        "subject": "test3",
+        "version":  3
+      }
+    ],
+    "metadata": {
+      "tags": {
+        "tag1": [
+          "PII"
+        ],
+        "tag2": [
+          "PIIIII"
+        ]
+      },
+      "properties": {
+        "email": "bob@acme.com",
+        "owner": "Bob Jones"
+      },
+      "sensitive": [
+        "s1",
+        "s2"
+      ]
+    }
+  }
+]
diff --git a/internal/testdata/schema_registry_schema/read_ruleset_delete_latest.json b/internal/testdata/schema_registry_schema/read_ruleset_delete_latest.json
new file mode 100644
index 000000000..327e9b4ba
--- /dev/null
+++ b/internal/testdata/schema_registry_schema/read_ruleset_delete_latest.json
@@ -0,0 +1,18 @@
+{
+  "subject": "test2",
+  "version": 8,
+  "id": 100001,
+  "schema": "foobar",
+  "references": [
+    {
+      "name": "sampleRecord",
+      "subject": "test2",
+      "version": 9
+    },
+    {
+      "name": "sampleRecord2",
+      "subject": "test3",
+      "version":  3
+    }
+  ]
+}
\ No newline at end of file


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR addresses a ruleset deletion issue by updating test expectations and the provider’s schema handling for an empty ruleset. Key changes include:
- Updating tests to assert that the ruleset is removed (i.e., "ruleset.#" equals "0") in both standard and enhanced provider block tests.
- Adjusting the resource schema by changing "Computed" from true to false and updating the diff handling to correctly set an empty ruleset when it is removed.

### Reviewed Changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 1 comment.

| File | Description |
| ---- | ----------- |
| internal/provider/resource_schema_latest_test.go | Updated tests to expect ruleset deletion instead of populated ruleset details. |
| internal/provider/resource_schema_latest_provider_block_test.go | Similar test updates for provider block; commented-out checks indicate prior detailed ruleset validations are no longer used. |
| internal/provider/resource_schema.go | Adjusted the ruleset schema definition and diff handling logic to create an empty ruleset when needed. |

<details>
<summary>Files not reviewed (1)</summary>

* **internal/testdata/schema_registry_schema/read_schemas.json**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**internal/provider/resource_schema.go:190**
* [nitpick] Verify that the change of 'Computed' from true to false is fully covered by tests to ensure the provider handles state refresh accurately.
```
Computed: false,
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-04-18T22:04:37Z
user: login: tmalikconfluent
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-21T19:51:55Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-22T18:43:27Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:28:05Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:28:42Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:32:39Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:33:57Z
user: login: linouk23
body: Looks great!
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:34:06Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:34:58Z
user: login: tmalikconfluent
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:39:59Z
user: login: tmalikconfluent
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:40:13Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:43:40Z
user: login: tmalikconfluent
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:45:28Z
user: login: tmalikconfluent
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:46:06Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:46:09Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:48:10Z
user: login: linouk23
body: Looks great! Left a few minor suggestions.
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:48:20Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T18:58:32Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-23T20:49:03Z
user: login: sgagniere
body: nitpick:
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T20:58:01Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:12:19Z
user: login: linouk23
body: I created another doc with test results: https://docs.google.com/document/d/1BcLmJWdvj0BF5FcbLlbTaIHDTrPb0PUi9DjSORci1K8/edit?usp=sharing and the results look promising 👏 
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:13:23Z
user: login: linouk23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T08:20:14Z
user: login: linouk23
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-20T17:20:01Z

Review comments:
diff_hunk: @@ -157,37 +157,37 @@ func TestAccLatestSchemaWithEnhancedProviderBlock(t *testing.T) {
 					resource.TestCheckNoResourceAttr(fullSchemaResourceLabel, "credentials.0.secret"),
 					resource.TestCheckNoResourceAttr(fullSchemaResourceLabel, "rest_endpoint"),
 					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "%", strconv.Itoa(testNumberOfSchemaRegistrySchemaResourceAttributes)),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.#", "1"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.%", "2"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.#", "2"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.%", "11"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.doc", ""),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.expr", ""),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.kind", "TRANSFORM"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.mode", "WRITEREAD"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.name", "encrypt"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_failure", "ERROR,ERROR"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_success", "NONE,NONE"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.params.%", "1"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.params.encrypt.kek.name", "testkek2"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.tags.#", "1"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.tags.0", "PIIIII"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.type", "ENCRYPT"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.disabled", "false"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.%", "11"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.doc", ""),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.expr", ""),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.kind", "TRANSFORM"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.mode", "WRITEREAD"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.name", "encryptPII"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.on_failure", "ERROR,ERROR"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.on_success", "NONE,NONE"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.params.%", "1"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.params.encrypt.kek.name", "testkek2"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.tags.#", "1"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.tags.0", "PII"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.type", "ENCRYPT"),
-					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.1.disabled", "false"),
+					resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.#", "0"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.%", "2"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.#", "2"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.%", "11"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.doc", ""),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.expr", ""),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.kind", "TRANSFORM"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.mode", "WRITEREAD"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.name", "encrypt"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_failure", "ERROR,ERROR"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.on_success", "NONE,NONE"),
+					//resource.TestCheckResourceAttr(fullSchemaResourceLabel, "ruleset.0.domain_rules.0.params.%", "1"),
path: internal/provider/resource_schema_latest_provider_block_test.go
user: login: Copilot
body: [nitpick] Consider removing the commented-out test checks if they are no longer necessary, to reduce noise and potential confusion.
```suggestion
// Removed unnecessary commented-out test checks to reduce noise and potential confusion.
```
created_at: 2025-04-18T22:04:36Z
author_association: NONE
diff_hunk: @@ -350,13 +350,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 {
+			ruleset := sr.NewRuleSet()
+			ruleset.SetDomainRules([]sr.Rule{})
+			createSchemaRequest.SetRuleSet(*ruleset)
+		} else {
path: internal/provider/resource_schema.go
user: login: tmalikconfluent
body: add a comment explaining this 
created_at: 2025-04-21T19:51:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -97,37 +97,6 @@ func TestAccDataSourceSchema(t *testing.T) {
 					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "schema_reference.1.subject_name", testSecondSchemaReferenceSubject),
 					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "schema_reference.1.version", strconv.Itoa(testSecondSchemaReferenceVersion)),
 					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "%", strconv.Itoa(testNumberOfSchemaRegistrySchemaResourceAttributes)),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.#", "1"),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.0.%", "2"),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.0.domain_rules.#", "2"),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.0.domain_rules.0.%", "11"),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.0.domain_rules.0.doc", ""),
-					resource.TestCheckResourceAttr(fullSchemaDataSourceLabel, "ruleset.0.domain_rules.0.expr", ""),
path: internal/provider/data_source_schema_test.go
user: login: linouk23
body: Are these changes expected?
created_at: 2025-04-22T18:43:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -350,13 +350,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset.
path: internal/provider/resource_schema.go
user: login: linouk23
body: nit: let's add a boolean variable here to make it a bit more readable
created_at: 2025-04-23T18:28:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -350,13 +350,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset.
+			ruleset := sr.NewRuleSet()
+			ruleset.SetDomainRules([]sr.Rule{})
+			createSchemaRequest.SetRuleSet(*ruleset)
+		} else { //this is the case of adding a ruleset.
path: internal/provider/resource_schema.go
user: login: linouk23
body: Is it just for adding or _else_? For example, what about the scenario of going from 4 -> 3 rulesets?
created_at: 2025-04-23T18:28:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: linouk23
body: Do we want to update the docs to say how to delete rulesets? 
**Before**:
```
// additional rules:
  ruleset {
    domain_rules {
      name = "encryptPII"
      kind = "TRANSFORM"
      type = "ENCRYPT"
      mode = "WRITEREAD"
      tags = ["PII"]
      params = {
          "encrypt.kek.name" = "testkek2"
      }
    }
    domain_rules  {
      name = "encrypt"
      kind = "TRANSFORM"
      type = "ENCRYPT"
      mode = "WRITEREAD"
      tags = ["PIIIII"]
      params = {
          "encrypt.kek.name" = "testkek2"
      }
    }
  }
```
**After**:
Do we want users to have an empty `ruleset {}` still vs deleting `ruleset {}` completely in their TF config?
created_at: 2025-04-23T18:32:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: linouk23
body: Based on the testing doc, it seems like we used the latter. Can we try with `ruleset {}` to see whether this `Computed` change is going to be necessary?
created_at: 2025-04-23T18:33:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: linouk23
body: The reason I ask is `ruleset {}` matches with `ruleset.SetDomainRules([]sr.Rule{})` a bit closer.
created_at: 2025-04-23T18:34:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -350,13 +350,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset.
path: internal/provider/resource_schema.go
user: login: tmalikconfluent
body: the variable would only be used once, not sure if its a great idea
created_at: 2025-04-23T18:39:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -350,13 +350,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
-		ruleset := sr.NewRuleSet()
-		tfRulesetMap := tfRuleset[0].(map[string]interface{})
-		if tfRulesetMap[paramDomainRules] != nil {
-			ruleset.SetDomainRules(buildRules(tfRulesetMap[paramDomainRules].(*schema.Set).List()))
+		if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 { //this is the case of an advanced package user trying to delete a ruleset.
+			ruleset := sr.NewRuleSet()
+			ruleset.SetDomainRules([]sr.Rule{})
+			createSchemaRequest.SetRuleSet(*ruleset)
+		} else { //this is the case of adding a ruleset.
path: internal/provider/resource_schema.go
user: login: tmalikconfluent
body: yeah let me update the comment
created_at: 2025-04-23T18:40:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: linouk23
body: Do we know whether API returns `null` or `{}` after deleting the rulesets? I suspect it's the latter.
created_at: 2025-04-23T18:43:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: tmalikconfluent
body: i have tried with ruleset{} without the computed change already, and it doesn't work well
created_at: 2025-04-23T18:45:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: tmalikconfluent
body: We need to delete the ruleset completely , let me update the doc accordingly 
created_at: 2025-04-23T18:46:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -562,7 +569,12 @@ func schemaCreate(ctx context.Context, d *schema.ResourceData, meta interface{})
 	createSchemaRequest.SetSchemaType(format)
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
-	if tfRuleset := d.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
+	oldRuleset, newRuleset := d.GetChange(paramRuleset)
+	if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0 {
path: internal/provider/resource_schema.go
user: login: linouk23
body: let's add a comment similar to the one we've got in SetSchemaDiff()
created_at: 2025-04-23T18:46:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -267,6 +267,28 @@ func testAccCheckLatestRefreshSchemaConfig(confluentCloudBaseUrl, mockServerUrl
         subject_name = "%s"
         version = %d
       }
+  	  ruleset {
path: internal/provider/resource_schema_latest_refresh_test.go
user: login: linouk23
body: If it's not present already, is it possible to update one of the acceptance rulesets to include a test case for the "update" operation, which involves removing a ruleset?
created_at: 2025-04-23T18:48:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -187,7 +187,7 @@ func rulesetSchema() *schema.Schema {
 			},
 		},
 		MaxItems: 1,
path: internal/provider/resource_schema.go
user: login: linouk23
body: > and it doesn't work well

could you add it to the testing doc?
created_at: 2025-04-23T18:58:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -118,6 +118,8 @@ The following arguments are supported:
 
 -> **Note:** The Confluent Cloud Console uses the following default values: `on_success = "NONE"` and `on_failure = "ERROR"`. However, the TF Provider sets its defaults to `on_success = "NONE,NONE"` and `on_failure = "ERROR,ERROR"`.
 
+-> **Note:** To delete all schema rules from a schema, remove the ruleset block completely from the terraform file.
path: docs/resources/confluent_schema.md
user: login: linouk23
body: ```suggestion
-> **Note:** To delete all schema rules from a schema, remove the ruleset block completely from the Terraform configuration file.
```
created_at: 2025-04-23T20:49:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -118,6 +118,8 @@ The following arguments are supported:
 
 -> **Note:** The Confluent Cloud Console uses the following default values: `on_success = "NONE"` and `on_failure = "ERROR"`. However, the TF Provider sets its defaults to `on_success = "NONE,NONE"` and `on_failure = "ERROR,ERROR"`.
 
+-> **Note:** To delete all schema rules from a schema, remove the ruleset block completely from the Terraform configuration file..
path: docs/resources/confluent_schema.md
user: login: sgagniere
body: ```suggestion
-> **Note:** To delete all schema rules from a schema, remove the ruleset block completely from the Terraform configuration file.
```
created_at: 2025-05-13T20:46:23Z
author_association: MEMBER
diff_hunk: @@ -352,13 +352,20 @@ func SetSchemaDiff(ctx context.Context, diff *schema.ResourceDiff, meta interfac
 	createSchemaRequest.SetSchema(schemaContent)
 	createSchemaRequest.SetReferences(schemaReferences)
 
+	oldRuleset, newRuleset := diff.GetChange(paramRuleset)
 	if tfRuleset := diff.Get(paramRuleset).([]interface{}); len(tfRuleset) == 1 {
path: internal/provider/resource_schema.go
user: login: linouk23
body: Assuming `newRuleset` is the same as `diff.Get(paramRuleset)`, it seems like the condition:

```go
if len(newRuleset.([]interface{})) == 0 && len(oldRuleset.([]interface{})) > 0
```

may never be true, given the `len(tfRuleset) == 1` check on line 355. Could you add a TODO to revisit this logic later once we add migration rules as well??

I suspect it's effectively a no-op — removing a ruleset is always valid for advanced SG Packages, and Essentials won't hit `len(oldRuleset.([]interface{})) > 0` anyway.

created_at: 2025-05-20T08:12:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -121,6 +121,8 @@ The following arguments are supported:
 
 -> **Note:** The Confluent Cloud Console uses the following default values: `on_success = "NONE"` and `on_failure = "ERROR"`. However, the TF Provider sets its defaults to `on_success = "NONE,NONE"` and `on_failure = "ERROR,ERROR"`.
 
+-> **Note:** To delete all schema rules from a schema, remove the ruleset block completely from the Terraform configuration file.
path: docs/resources/confluent_schema.md
user: login: linouk23
body: nit:
![image](https://github.com/user-attachments/assets/eb9f88d6-c91f-438a-b62d-1944e88f5ced)
```
  ruleset {
    domain_rules {
      name = "encryptPII"
```

```suggestion
-> **Note:** To delete all domain rules from an existing schema, remove the `ruleset` block from the `confluent_schema` resource in the Terraform configuration.
```
created_at: 2025-05-20T08:20:14Z
author_association: CONTRIBUTOR

PR comments:
user: login: sonarqube-confluent[bot]
created_at: 2025-04-21T22:30:47Z
body: ![Passed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/passed.svg?sanitize=true)

# Analysis Details
## 2 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 2 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/25.svg?sanitize=true) 38.50% Coverage (79.50% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-22T20:17:37Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 53.80% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 2 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 2 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/50.svg?sanitize=true) 53.80% Coverage (79.80% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-23T21:15:55Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 53.80% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 2 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 2 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/50.svg?sanitize=true) 53.80% Coverage (79.80% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-04-23T23:42:23Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 76.90% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 2 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 2 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/60.svg?sanitize=true) 76.90% Coverage (79.80% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-05-19T18:58:00Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 76.90% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 2 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 2 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/60.svg?sanitize=true) 76.90% Coverage (79.70% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE
user: login: sonarqube-confluent[bot]
created_at: 2025-05-20T17:34:26Z
body: ![Failed](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/QualityGateBadge/failed.svg?sanitize=true)

- 76.90% Coverage on New Code (is less than 80.00%)

# Analysis Details
## 3 Issues
- ![Bug](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/bug.svg?sanitize=true) 0 Bugs
- ![Vulnerability](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/vulnerability.svg?sanitize=true) 0 Vulnerabilities
- ![Code Smell](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/common/code_smell.svg?sanitize=true) 3 Code Smells

## Coverage and Duplications
- ![Coverage](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/CoverageChart/60.svg?sanitize=true) 76.90% Coverage (79.70% Estimated after merge)
- ![Duplications](https://sonarqube.dp.confluent.io/static/communityBranchPlugin/checks/Duplications/NoDuplicationInfo.svg?sanitize=true) No duplication information (0.10% Estimated after merge)

**Project ID:** terraform-provider-confluent

[View in SonarQube](https://sonarqube.dp.confluent.io/dashboard?id=terraform-provider-confluent&pullRequest=654)


author_association: NONE