diff --git a/Cargo.lock b/Cargo.lock
index eb70a3b43..fb83fe46c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,7 +4,7 @@ version = 4
 
 [[package]]
 name = "account-for-display"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "derive_more",
@@ -49,10 +49,10 @@ dependencies = [
 
 [[package]]
 name = "addresses"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "cap26-models",
  "core-utils",
  "derive_more",
@@ -246,7 +246,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
 
 [[package]]
 name = "assert-json"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json-diff",
  "error",
@@ -546,7 +546,7 @@ dependencies = [
 
 [[package]]
 name = "build-info"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "cargo_toml",
@@ -573,7 +573,7 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
 
 [[package]]
 name = "bytes"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "delegate",
@@ -607,7 +607,7 @@ dependencies = [
 
 [[package]]
 name = "cap26-models"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "derive_more",
@@ -748,7 +748,7 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
 
 [[package]]
 name = "clients"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "async-trait",
@@ -808,7 +808,7 @@ checksum = "0d8a42181e0652c2997ae4d217f25b63c5337a52fd2279736e97b832fa0a3cff"
 
 [[package]]
 name = "core-collections"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "has-sample-values",
  "indexmap 2.7.0",
@@ -835,7 +835,7 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
 
 [[package]]
 name = "core-misc"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "core-utils",
@@ -855,7 +855,7 @@ dependencies = [
 
 [[package]]
 name = "core-utils"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "error",
  "iso8601-timestamp",
@@ -1084,7 +1084,7 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
 
 [[package]]
 name = "drivers"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -1108,10 +1108,10 @@ dependencies = [
 
 [[package]]
 name = "ecc"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "derive_more",
  "enum-as-inner",
  "error",
@@ -1210,11 +1210,11 @@ dependencies = [
 
 [[package]]
 name = "encryption"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "aes-gcm",
  "assert-json",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "derive_more",
  "error",
  "has-sample-values",
@@ -1231,7 +1231,7 @@ dependencies = [
 
 [[package]]
 name = "entity-by-address"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "error",
@@ -1243,7 +1243,7 @@ dependencies = [
 
 [[package]]
 name = "entity-foundation"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "derive_more",
@@ -1318,7 +1318,7 @@ dependencies = [
 
 [[package]]
 name = "error"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "derive_more",
  "log",
@@ -1377,7 +1377,7 @@ dependencies = [
 
 [[package]]
 name = "factor-instances-provider"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -1403,9 +1403,9 @@ dependencies = [
 
 [[package]]
 name = "factors"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "cap26-models",
  "core-collections",
  "core-misc",
@@ -1440,7 +1440,7 @@ dependencies = [
 
 [[package]]
 name = "factors-supporting-types"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "async-trait",
  "error",
@@ -1593,7 +1593,7 @@ dependencies = [
 
 [[package]]
 name = "gateway-client-and-api"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -1613,7 +1613,7 @@ dependencies = [
 
 [[package]]
 name = "gateway-models"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "assert-json",
@@ -1718,7 +1718,7 @@ dependencies = [
 
 [[package]]
 name = "has-sample-values"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "error",
  "indexmap 2.7.0",
@@ -1729,9 +1729,9 @@ dependencies = [
 
 [[package]]
 name = "hash"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "derive_more",
  "prelude",
  "radix-common",
@@ -1795,11 +1795,11 @@ dependencies = [
 
 [[package]]
 name = "hierarchical-deterministic"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "bip39",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "cap26-models",
  "derive_more",
  "ecc",
@@ -1842,13 +1842,13 @@ dependencies = [
 
 [[package]]
 name = "home-cards"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
  "async-trait",
  "base64",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "core-utils",
  "derive_more",
  "drivers",
@@ -1868,7 +1868,7 @@ dependencies = [
 
 [[package]]
 name = "host-info"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "derive_more",
@@ -1915,10 +1915,10 @@ dependencies = [
 
 [[package]]
 name = "http-client"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "core-utils",
  "drivers",
  "error",
@@ -2143,7 +2143,7 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "identified-vec-of"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "derive_more",
@@ -2216,7 +2216,7 @@ dependencies = [
 
 [[package]]
 name = "interactors"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "async-trait",
  "derive_more",
@@ -2336,7 +2336,7 @@ dependencies = [
 
 [[package]]
 name = "key-derivation-traits"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "async-trait",
@@ -2354,7 +2354,7 @@ dependencies = [
 
 [[package]]
 name = "keys-collector"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -2443,7 +2443,7 @@ dependencies = [
 
 [[package]]
 name = "manifests"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "account-for-display",
  "addresses",
@@ -2483,7 +2483,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "metadata"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "derive_more",
  "has-sample-values",
@@ -2583,7 +2583,7 @@ dependencies = [
 
 [[package]]
 name = "network"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
  "enum-iterator",
@@ -2599,7 +2599,7 @@ dependencies = [
 
 [[package]]
 name = "next-derivation-index-ephemeral"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "assert-json",
@@ -2675,9 +2675,9 @@ dependencies = [
 
 [[package]]
 name = "numeric"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "delegate",
  "derive_more",
  "enum-iterator",
@@ -2897,7 +2897,7 @@ dependencies = [
 
 [[package]]
 name = "prelude"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "radix-engine",
  "radix-engine-toolkit",
@@ -2934,7 +2934,7 @@ dependencies = [
 
 [[package]]
 name = "profile"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "account-for-display",
  "addresses",
@@ -2978,7 +2978,7 @@ dependencies = [
 
 [[package]]
 name = "profile-account"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "account-for-display",
  "addresses",
@@ -2998,7 +2998,7 @@ dependencies = [
 
 [[package]]
 name = "profile-account-or-persona"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "cap26-models",
  "derive_more",
@@ -3015,7 +3015,7 @@ dependencies = [
 
 [[package]]
 name = "profile-app-preferences"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "core-misc",
@@ -3038,7 +3038,7 @@ dependencies = [
 
 [[package]]
 name = "profile-base-entity"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "derive_more",
@@ -3061,7 +3061,7 @@ dependencies = [
 
 [[package]]
 name = "profile-gateway"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "assert-json",
@@ -3085,7 +3085,7 @@ dependencies = [
 
 [[package]]
 name = "profile-logic"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "derive_more",
@@ -3107,7 +3107,7 @@ dependencies = [
 
 [[package]]
 name = "profile-persona"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "cap26-models",
@@ -3128,7 +3128,7 @@ dependencies = [
 
 [[package]]
 name = "profile-persona-data"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "assert-json",
@@ -3147,11 +3147,12 @@ dependencies = [
 
 [[package]]
 name = "profile-security-structures"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "cap26-models",
  "core-collections",
+ "core-misc",
  "core-utils",
  "derive_more",
  "enum-as-inner",
@@ -3174,7 +3175,7 @@ dependencies = [
 
 [[package]]
 name = "profile-state-holder"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "derive_more",
  "error",
@@ -3189,7 +3190,7 @@ dependencies = [
 
 [[package]]
 name = "profile-supporting-types"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "derive_more",
@@ -3278,14 +3279,14 @@ dependencies = [
 
 [[package]]
 name = "radix-connect"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
  "assert-json",
  "async-trait",
  "base64",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "core-misc",
  "core-utils",
  "derive_more",
@@ -3313,10 +3314,10 @@ dependencies = [
 
 [[package]]
 name = "radix-connect-models"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "core-misc",
  "derive_more",
  "error",
@@ -3758,7 +3759,7 @@ dependencies = [
 
 [[package]]
 name = "sargon"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -3822,7 +3823,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "async-trait",
@@ -3849,7 +3850,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os-accounts"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -3872,7 +3873,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os-factors"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "async-trait",
@@ -3895,7 +3896,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os-security-center"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "derive_more",
@@ -3911,7 +3912,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os-signing"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "async-trait",
@@ -3937,7 +3938,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-os-transaction"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "async-std",
@@ -3966,7 +3967,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-uniffi"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
@@ -4023,7 +4024,7 @@ dependencies = [
 
 [[package]]
 name = "sargon-uniffi-conversion-macros"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4196,7 +4197,7 @@ dependencies = [
 
 [[package]]
 name = "security-center"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
  "assert-json",
@@ -4364,7 +4365,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
 [[package]]
 name = "short-string"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "arraystring",
  "assert-json",
@@ -4399,13 +4400,13 @@ dependencies = [
 
 [[package]]
 name = "signing"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "actix-rt",
  "addresses",
  "assert-json",
  "async-trait",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "cap26-models",
  "core-collections",
  "core-misc",
@@ -4437,10 +4438,10 @@ dependencies = [
 
 [[package]]
 name = "signing-traits"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "async-trait",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "core-collections",
  "derive_more",
  "ecc",
@@ -4605,7 +4606,7 @@ dependencies = [
 
 [[package]]
 name = "sub-systems"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "derive_more",
  "drivers",
@@ -4764,7 +4765,7 @@ dependencies = [
 
 [[package]]
 name = "time-utils"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "iso8601-timestamp",
  "prelude",
@@ -4914,10 +4915,10 @@ dependencies = [
 
 [[package]]
 name = "transaction-foundation"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "assert-json",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "derive_more",
  "has-sample-values",
  "paste",
@@ -4929,10 +4930,10 @@ dependencies = [
 
 [[package]]
 name = "transaction-models"
-version = "1.1.112"
+version = "1.1.113"
 dependencies = [
  "addresses",
- "bytes 1.1.112",
+ "bytes 1.1.113",
  "cargo_toml",
  "core-collections",
  "core-misc",
diff --git a/apple/Tests/TestCases/Profile/MFA/SecurityShieldsBuilderTests.swift b/apple/Tests/TestCases/Profile/MFA/SecurityShieldsBuilderTests.swift
index 9505791ab..cc1e8e817 100644
--- a/apple/Tests/TestCases/Profile/MFA/SecurityShieldsBuilderTests.swift
+++ b/apple/Tests/TestCases/Profile/MFA/SecurityShieldsBuilderTests.swift
@@ -58,7 +58,7 @@ struct ShieldTests {
 	@Test("primary override validation status trustedContact")
 	func primValidationStatusTrustedContact() {
 		let builder = SecurityShieldBuilder()
-		#expect(builder.validationForAdditionOfFactorSourceToPrimaryOverrideForEach(factorSources: [TrustedContactFactorSource.sample.asGeneral.id]).compactMap(\.reasonIfInvalid) == [FactorSourceValidationStatusReasonIfInvalid.nonBasic(SecurityShieldBuilderInvalidReason.PrimaryCannotContainTrustedContact)])
+		#expect(builder.validationForAdditionOfFactorSourceToPrimaryOverrideForEach(factorSources: [TrustedContactFactorSource.sample.asGeneral.id]).compactMap(\.reasonIfInvalid) == [FactorSourceValidationStatusReasonIfInvalid.nonBasic(SecurityShieldBuilderRuleViolation.PrimaryCannotContainTrustedContact)])
 	}
 
 	@Test("Auto lowering of threshold upon deletion")
@@ -88,32 +88,6 @@ struct ShieldTests {
 		#expect(builder.primaryRoleThresholdFactors == [])
 	}
 
-	@Test("basic validation")
-	func basicValidation() throws {
-		var builder = SecurityShieldBuilder()
-		#expect(builder.validate() == .MissingAuthSigningFactor)
-		builder = builder.setAuthenticationSigningFactor(new: .sampleDevice)
-		#expect(builder.validate() == .PrimaryRoleMustHaveAtLeastOneFactor)
-		builder = builder.addFactorSourceToPrimaryThreshold(factorSourceId: .sampleDevice)
-			.addFactorSourceToPrimaryThreshold(factorSourceId: .sampleDevice) // did not get added, duplicates are not allowed
-		#expect(builder.primaryRoleThresholdFactors == [.sampleDevice])
-
-		builder = builder.addFactorSourceToPrimaryThreshold(factorSourceId: .sampleDeviceOther) // actually this is added
-		#expect(builder.validate() == .PrimaryCannotHaveMultipleDevices)
-		builder = builder.removeFactorFromPrimary(factorSourceId: .sampleDeviceOther, factorListKind: FactorListKind.threshold)
-
-		#expect(builder.validate() == .RecoveryRoleMustHaveAtLeastOneFactor)
-		builder = builder.removeFactorFromPrimary(factorSourceId: .sampleDeviceOther, factorListKind: FactorListKind.threshold)
-			.addFactorSourceToRecoveryOverride(factorSourceId: .sampleLedger)
-
-		#expect(builder.validate() == .ConfirmationRoleMustHaveAtLeastOneFactor)
-		builder = builder.addFactorSourceToConfirmationOverride(factorSourceId: .sampleArculus)
-			.setAuthenticationSigningFactor(new: .sampleDevice)
-
-		#expect(builder.validate() == nil)
-		#expect((try? builder.build()) != nil)
-	}
-
 	@Test("cannot add forbidden FactorSourceKinds")
 	func preventAddOfForbiddenFactorSourceKinds() throws {
 		let builder = SecurityShieldBuilder()
@@ -147,49 +121,17 @@ struct ShieldTests {
 		#expect(builder.primaryRoleThresholdFactors == [other])
 		#expect(builder.primaryRoleOverrideFactors == [other, factor])
 
-		// But when validated/built is err
-		#expect(builder.validate() != nil)
+		// But when statusd/built is err
+		#expect(builder.status() != nil)
 		#expect((try? builder.build()) == nil)
 	}
 
-	@Test("Primary password never alone")
-	func primaryPasswordNeverAlone() {
-		var builder = SecurityShieldBuilder()
-			.setAuthenticationSigningFactor(new: .sampleDevice)
-			.addFactorSourceToPrimaryOverride(factorSourceId: .samplePassword) // not allowed
-		#expect(builder.primaryRoleOverrideFactors.isEmpty)
-
-		builder = builder.addFactorSourceToPrimaryThreshold(factorSourceId: .samplePassword)
-		#expect(builder.validate() == .PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor)
-		builder = builder.setThreshold(threshold: Threshold.all)
-
-		builder = builder.setThreshold(threshold: Threshold.specific(1))
-		#expect(builder.validate() == .PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor)
-		builder = builder.addFactorSourceToPrimaryThreshold(factorSourceId: .sampleLedger)
-		#expect(builder.validate() == .PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne)
-		builder = builder.setThreshold(threshold: Threshold.specific(2))
-
-		builder = builder.addFactorSourceToRecoveryOverride(factorSourceId: .sampleArculus)
-			.addFactorSourceToConfirmationOverride(factorSourceId: .sampleArculusOther)
-
-		builder = builder.setAuthenticationSigningFactor(new: .sampleDevice)
-
-		let shield = try! builder.build()
-
-		#expect(shield.matrixOfFactors.primaryRole.overrideFactors.isEmpty)
-		#expect(shield.matrixOfFactors.primaryRole.threshold == Threshold.specific(2))
-		#expect(shield.matrixOfFactors.primaryRole.thresholdFactors == [.samplePassword, .sampleLedger])
-	}
-
 	@Test("Build")
 	func build() throws {
 		var builder = SecurityShieldBuilder()
 			.setName(name: "S.H.I.E.L.D.")
 			.setTimePeriodUntilAutoConfirm(timePeriod: TimePeriod(days: 42))
-
-		#expect(builder.validate() == .MissingAuthSigningFactor)
-		builder = builder.setAuthenticationSigningFactor(new: .sampleDevice)
-		#expect(builder.validate() == .PrimaryRoleMustHaveAtLeastOneFactor)
+			.setAuthenticationSigningFactor(new: .sampleDevice)
 
 		// Primary
 		#expect(builder.threshold == Threshold.all)
@@ -208,8 +150,8 @@ struct ShieldTests {
 
 		builder = builder.setAuthenticationSigningFactor(new: .sampleDevice)
 
-		// Validate
-		#expect(builder.validate() == nil)
+		// status
+		#expect(builder.status() == SecurityShieldBuilderStatus.strong)
 
 		// Build
 		let shield0 = try builder.build()
diff --git a/crates/app/home-cards/Cargo.toml b/crates/app/home-cards/Cargo.toml
index b94c7ec1a..9167e5bbc 100644
--- a/crates/app/home-cards/Cargo.toml
+++ b/crates/app/home-cards/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "home-cards"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/app/key-derivation-traits/Cargo.toml b/crates/app/key-derivation-traits/Cargo.toml
index 968deb2ff..aa2181e84 100644
--- a/crates/app/key-derivation-traits/Cargo.toml
+++ b/crates/app/key-derivation-traits/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "key-derivation-traits"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/app/radix-connect-models/Cargo.toml b/crates/app/radix-connect-models/Cargo.toml
index 46360cf89..6aaf12e66 100644
--- a/crates/app/radix-connect-models/Cargo.toml
+++ b/crates/app/radix-connect-models/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "radix-connect-models"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/app/radix-connect/Cargo.toml b/crates/app/radix-connect/Cargo.toml
index 1525a92b2..e77e607fe 100644
--- a/crates/app/radix-connect/Cargo.toml
+++ b/crates/app/radix-connect/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "radix-connect"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/app/security-center/Cargo.toml b/crates/app/security-center/Cargo.toml
index 84c578372..4531b1bef 100644
--- a/crates/app/security-center/Cargo.toml
+++ b/crates/app/security-center/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "security-center"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/app/signing-traits/Cargo.toml b/crates/app/signing-traits/Cargo.toml
index 5ec057255..cead4d41e 100644
--- a/crates/app/signing-traits/Cargo.toml
+++ b/crates/app/signing-traits/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "signing-traits"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/app/signing/Cargo.toml b/crates/app/signing/Cargo.toml
index 3a583d966..c50c4d42b 100644
--- a/crates/app/signing/Cargo.toml
+++ b/crates/app/signing/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "signing"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/common/build-info/Cargo.toml b/crates/common/build-info/Cargo.toml
index 10c74ce30..97114472b 100644
--- a/crates/common/build-info/Cargo.toml
+++ b/crates/common/build-info/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "build-info"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 build = "build.rs"
 
diff --git a/crates/common/bytes/Cargo.toml b/crates/common/bytes/Cargo.toml
index c4b0d4835..2f75a9121 100644
--- a/crates/common/bytes/Cargo.toml
+++ b/crates/common/bytes/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "bytes"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/entity-foundation/Cargo.toml b/crates/common/entity-foundation/Cargo.toml
index a6fd11e1e..dcdf1d273 100644
--- a/crates/common/entity-foundation/Cargo.toml
+++ b/crates/common/entity-foundation/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "entity-foundation"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/host-info/Cargo.toml b/crates/common/host-info/Cargo.toml
index 926b78a4b..55db36670 100644
--- a/crates/common/host-info/Cargo.toml
+++ b/crates/common/host-info/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "host-info"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/identified-vec-of/Cargo.toml b/crates/common/identified-vec-of/Cargo.toml
index 75b24a578..f5c64745c 100644
--- a/crates/common/identified-vec-of/Cargo.toml
+++ b/crates/common/identified-vec-of/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "identified-vec-of"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/metadata/Cargo.toml b/crates/common/metadata/Cargo.toml
index 61fa289ad..24d75367c 100644
--- a/crates/common/metadata/Cargo.toml
+++ b/crates/common/metadata/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "metadata"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/network/Cargo.toml b/crates/common/network/Cargo.toml
index 9bbef0ea7..8431092e3 100644
--- a/crates/common/network/Cargo.toml
+++ b/crates/common/network/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "network"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/numeric/Cargo.toml b/crates/common/numeric/Cargo.toml
index f4fc17bb8..55fb99efe 100644
--- a/crates/common/numeric/Cargo.toml
+++ b/crates/common/numeric/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "numeric"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/common/short-string/Cargo.toml b/crates/common/short-string/Cargo.toml
index 0e78c3af1..e93264a8b 100644
--- a/crates/common/short-string/Cargo.toml
+++ b/crates/common/short-string/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "short-string"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/assert-json/Cargo.toml b/crates/core/assert-json/Cargo.toml
index 7ed128574..980584767 100644
--- a/crates/core/assert-json/Cargo.toml
+++ b/crates/core/assert-json/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "assert-json"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/collections/Cargo.toml b/crates/core/collections/Cargo.toml
index f5c4c1fbe..911b7b174 100644
--- a/crates/core/collections/Cargo.toml
+++ b/crates/core/collections/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "core-collections"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/error/Cargo.toml b/crates/core/error/Cargo.toml
index 013614eb4..f67bd3413 100644
--- a/crates/core/error/Cargo.toml
+++ b/crates/core/error/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "error"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/error/src/common_error.rs b/crates/core/error/src/common_error.rs
index d80aeb024..aaa82214a 100644
--- a/crates/core/error/src/common_error.rs
+++ b/crates/core/error/src/common_error.rs
@@ -859,6 +859,11 @@ pub enum CommonError {
 
     #[error("Signing failed due to too many factor sources were neglected.")]
     SigningFailedTooManyFactorSourcesNeglected = 10247,
+
+    #[error(
+        "SecurityStructure already exists in profile, FactorSourceID {bad_value}."
+    )]
+    StructureAlreadyExists { bad_value: String } = 10248,
 }
 
 impl CommonError {
diff --git a/crates/core/has-sample-values/Cargo.toml b/crates/core/has-sample-values/Cargo.toml
index 8896ab05d..5d17cb24d 100644
--- a/crates/core/has-sample-values/Cargo.toml
+++ b/crates/core/has-sample-values/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "has-sample-values"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/misc/Cargo.toml b/crates/core/misc/Cargo.toml
index 357e17fa3..f45f31cb6 100644
--- a/crates/core/misc/Cargo.toml
+++ b/crates/core/misc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "core-misc"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/prelude/Cargo.toml b/crates/core/prelude/Cargo.toml
index 383f8c14c..554402d1e 100644
--- a/crates/core/prelude/Cargo.toml
+++ b/crates/core/prelude/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "prelude"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/time-utils/Cargo.toml b/crates/core/time-utils/Cargo.toml
index 069943ebb..eb5df8182 100644
--- a/crates/core/time-utils/Cargo.toml
+++ b/crates/core/time-utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "time-utils"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/utils/Cargo.toml b/crates/core/utils/Cargo.toml
index 5418bcbcf..c8926192a 100644
--- a/crates/core/utils/Cargo.toml
+++ b/crates/core/utils/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "core-utils"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/core/utils/src/constants.rs b/crates/core/utils/src/constants.rs
index e54bea9f7..5841852c5 100644
--- a/crates/core/utils/src/constants.rs
+++ b/crates/core/utils/src/constants.rs
@@ -34,9 +34,6 @@ pub const MINUTES_PER_DAY: u32 = 24 * 60;
 /// Number of days per week.
 pub const DAYS_PER_WEEK: u16 = 7;
 
-/// Number of days per year.
-pub const DAYS_PER_YEAR: u16 = 365;
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/crates/crypto/addresses/Cargo.toml b/crates/crypto/addresses/Cargo.toml
index 1c89b4074..a6fb9aa1e 100644
--- a/crates/crypto/addresses/Cargo.toml
+++ b/crates/crypto/addresses/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "addresses"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/crypto/cap26-models/Cargo.toml b/crates/crypto/cap26-models/Cargo.toml
index e36456089..812e75e64 100644
--- a/crates/crypto/cap26-models/Cargo.toml
+++ b/crates/crypto/cap26-models/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "cap26-models"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/crypto/ecc/Cargo.toml b/crates/crypto/ecc/Cargo.toml
index f97db86fb..91cddd586 100644
--- a/crates/crypto/ecc/Cargo.toml
+++ b/crates/crypto/ecc/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ecc"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/crypto/encryption/Cargo.toml b/crates/crypto/encryption/Cargo.toml
index dd1bf1146..02215be71 100644
--- a/crates/crypto/encryption/Cargo.toml
+++ b/crates/crypto/encryption/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "encryption"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/crypto/hash/Cargo.toml b/crates/crypto/hash/Cargo.toml
index 902abfb24..378d1f3f1 100644
--- a/crates/crypto/hash/Cargo.toml
+++ b/crates/crypto/hash/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "hash"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/crypto/hd/Cargo.toml b/crates/crypto/hd/Cargo.toml
index 5e53bbe01..1c568e2ea 100644
--- a/crates/crypto/hd/Cargo.toml
+++ b/crates/crypto/hd/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "hierarchical-deterministic"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/factors/factors/Cargo.toml b/crates/factors/factors/Cargo.toml
index b6b758f99..cc141d5f7 100644
--- a/crates/factors/factors/Cargo.toml
+++ b/crates/factors/factors/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "factors"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/factors/instances-provider/Cargo.toml b/crates/factors/instances-provider/Cargo.toml
index 6d5203840..78e71d53e 100644
--- a/crates/factors/instances-provider/Cargo.toml
+++ b/crates/factors/instances-provider/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "factor-instances-provider"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/factors/keys-collector/Cargo.toml b/crates/factors/keys-collector/Cargo.toml
index 26d97e7c4..c22ae26be 100644
--- a/crates/factors/keys-collector/Cargo.toml
+++ b/crates/factors/keys-collector/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "keys-collector"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/factors/next-derivation-index-ephemeral/Cargo.toml b/crates/factors/next-derivation-index-ephemeral/Cargo.toml
index e10b7a1d5..1b0e5c3dd 100644
--- a/crates/factors/next-derivation-index-ephemeral/Cargo.toml
+++ b/crates/factors/next-derivation-index-ephemeral/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "next-derivation-index-ephemeral"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/factors/supporting-types/Cargo.toml b/crates/factors/supporting-types/Cargo.toml
index 2281c1b0d..47d542e19 100644
--- a/crates/factors/supporting-types/Cargo.toml
+++ b/crates/factors/supporting-types/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "factors-supporting-types"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/gateway/client-and-api/Cargo.toml b/crates/gateway/client-and-api/Cargo.toml
index 45125d93c..a8754c2d5 100644
--- a/crates/gateway/client-and-api/Cargo.toml
+++ b/crates/gateway/client-and-api/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "gateway-client-and-api"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/gateway/models/Cargo.toml b/crates/gateway/models/Cargo.toml
index 5a092ffe2..79c2260ce 100644
--- a/crates/gateway/models/Cargo.toml
+++ b/crates/gateway/models/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "gateway-models"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/profile/logic/logic_SPLIT_ME/Cargo.toml b/crates/profile/logic/logic_SPLIT_ME/Cargo.toml
index 4a3ac9f1a..bf2d4d96a 100644
--- a/crates/profile/logic/logic_SPLIT_ME/Cargo.toml
+++ b/crates/profile/logic/logic_SPLIT_ME/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-logic"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/account-for-display/Cargo.toml b/crates/profile/models/account-for-display/Cargo.toml
index 97b036e8f..b1696eab4 100644
--- a/crates/profile/models/account-for-display/Cargo.toml
+++ b/crates/profile/models/account-for-display/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "account-for-display"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/account-or-persona/Cargo.toml b/crates/profile/models/account-or-persona/Cargo.toml
index 77499663e..ef3189974 100644
--- a/crates/profile/models/account-or-persona/Cargo.toml
+++ b/crates/profile/models/account-or-persona/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-account-or-persona"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/account/Cargo.toml b/crates/profile/models/account/Cargo.toml
index 89707b88e..0ad2f25e8 100644
--- a/crates/profile/models/account/Cargo.toml
+++ b/crates/profile/models/account/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-account"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/app-preferences/Cargo.toml b/crates/profile/models/app-preferences/Cargo.toml
index 41568fef4..a0b4fe3f7 100644
--- a/crates/profile/models/app-preferences/Cargo.toml
+++ b/crates/profile/models/app-preferences/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-app-preferences"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/base-entity/Cargo.toml b/crates/profile/models/base-entity/Cargo.toml
index e2e20c9ec..bbcd4252e 100644
--- a/crates/profile/models/base-entity/Cargo.toml
+++ b/crates/profile/models/base-entity/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-base-entity"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/gateway/Cargo.toml b/crates/profile/models/gateway/Cargo.toml
index 94729a404..8064ef8af 100644
--- a/crates/profile/models/gateway/Cargo.toml
+++ b/crates/profile/models/gateway/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-gateway"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/persona-data/Cargo.toml b/crates/profile/models/persona-data/Cargo.toml
index aec3711f5..b585c8a8c 100644
--- a/crates/profile/models/persona-data/Cargo.toml
+++ b/crates/profile/models/persona-data/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-persona-data"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/persona/Cargo.toml b/crates/profile/models/persona/Cargo.toml
index 61bf951ab..ea4802d95 100644
--- a/crates/profile/models/persona/Cargo.toml
+++ b/crates/profile/models/persona/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-persona"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/models/profile_SPLIT_ME/Cargo.toml b/crates/profile/models/profile_SPLIT_ME/Cargo.toml
index 54810f84a..574822919 100644
--- a/crates/profile/models/profile_SPLIT_ME/Cargo.toml
+++ b/crates/profile/models/profile_SPLIT_ME/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/profile/models/security-structures/Cargo.toml b/crates/profile/models/security-structures/Cargo.toml
index 35bdfd30c..13faf1591 100644
--- a/crates/profile/models/security-structures/Cargo.toml
+++ b/crates/profile/models/security-structures/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-security-structures"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
@@ -18,7 +18,7 @@ core-collections = { workspace = true }
 time-utils = { workspace = true }
 short-string = { workspace = true }
 core-utils = { workspace = true }
-
+core-misc = { workspace = true }          # decl_bool_type
 
 # === RADIX DEPENDENCIES ===
 radix-engine-interface = { workspace = true }
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs
index f83e083f6..402a3a3c8 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/matrices/builder/matrix_builder.rs
@@ -37,19 +37,19 @@ impl MatrixBuilder {
     ///
     /// If valid it returns a "built" `MatrixOfFactorSourceIds`.
     pub fn build(&self) -> MatrixBuilderBuildResult {
-        self.validate_combination()?;
+        self.validate_number_of_days_until_auto_confirm()?;
 
         let primary = self
             .primary_role
-            .build()
+            .build_with_minimum_validation()
             .into_matrix_err(RoleKind::Primary)?;
         let recovery = self
             .recovery_role
-            .build()
+            .build_with_minimum_validation()
             .into_matrix_err(RoleKind::Recovery)?;
         let confirmation = self
             .confirmation_role
-            .build()
+            .build_with_minimum_validation()
             .into_matrix_err(RoleKind::Confirmation)?;
 
         let built = unsafe {
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/mod.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/mod.rs
index 2dd09a83e..2f4515524 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/mod.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/mod.rs
@@ -4,7 +4,8 @@ mod has_role_kind;
 mod matrices;
 mod roles;
 mod security_shield_builder;
-mod security_shield_builder_invalid_reason;
+mod security_shield_builder_rule_violation;
+mod security_shield_builder_status;
 mod security_shield_prerequisites_status;
 mod security_structure_id;
 mod security_structure_metadata;
@@ -17,7 +18,8 @@ pub use has_role_kind::*;
 pub use matrices::*;
 pub use roles::*;
 pub use security_shield_builder::*;
-pub use security_shield_builder_invalid_reason::*;
+pub use security_shield_builder_rule_violation::*;
+pub use security_shield_builder_status::*;
 pub use security_shield_prerequisites_status::*;
 pub use security_structure_id::*;
 pub use security_structure_metadata::*;
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/primary_roles_builder_unit_tests.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/primary_roles_builder_unit_tests.rs
index 24f0805e5..07255620f 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/primary_roles_builder_unit_tests.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/primary_roles_builder_unit_tests.rs
@@ -413,6 +413,22 @@ mod threshold_suite {
         );
     }
 
+    #[test]
+    fn set_threshold_from_one_to_all() {
+        // Arrange
+        let mut sut = make();
+
+        // Act
+        sut.add_factor_source_to_threshold(sample()).unwrap();
+        sut.add_factor_source_to_threshold(sample_other()).unwrap();
+        assert_eq!(sut.set_specific_threshold(2), Ok(()));
+        sut.remove_factor_source(&sample(), FactorListKind::Threshold)
+            .unwrap();
+
+        // Assert
+        assert_eq!(sut.set_threshold(Threshold::All), Ok(()));
+    }
+
     #[test]
     fn validation_for_addition_of_factor_source_for_each_before_after_adding_a_factor(
     ) {
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/roles_builder.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/roles_builder.rs
index 96a05667c..1502d03da 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/roles_builder.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/roles/builder/roles_builder.rs
@@ -375,6 +375,18 @@ impl<const ROLE: u8> RoleBuilder<ROLE> {
         })
     }
 
+    pub(crate) fn build_with_minimum_validation(
+        &self,
+    ) -> Result<RoleWithFactorSourceIds<ROLE>, RoleBuilderValidation> {
+        self.validate_minimum_factor_count().map(|_| {
+            RoleWithFactorSourceIds::with_factors_and_threshold(
+                self.get_threshold(),
+                self.get_threshold_factors().clone(),
+                self.get_override_factors().clone(),
+            )
+        })
+    }
+
     pub(crate) fn set_specific_threshold(
         &mut self,
         threshold: u8,
@@ -488,6 +500,12 @@ impl<const ROLE: u8> RoleBuilder<ROLE> {
             self.validation_for_addition_of_password_to_primary(Threshold)?;
         }
 
+        self.validate_minimum_factor_count()?;
+
+        Ok(())
+    }
+
+    fn validate_minimum_factor_count(&self) -> RoleBuilderMutateResult {
         if self.all_factors().is_empty() {
             return RoleBuilderMutateResult::not_yet_valid(
                 RoleMustHaveAtLeastOneFactor,
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs
index 7dd24bc9a..04ca46738 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder.rs
@@ -489,7 +489,7 @@ impl SecurityShieldBuilder {
     ) -> RoleBuilderMutateResult {
         self.get(|builder| {
             builder.validation_for_addition_of_factor_source_of_kind_to_confirmation_override(
-                factor_source_kind
+                factor_source_kind,
             )
         })
     }
@@ -500,7 +500,7 @@ impl SecurityShieldBuilder {
     ) -> RoleBuilderMutateResult {
         self.get(|builder| {
             builder.validation_for_addition_of_factor_source_of_kind_to_recovery_override(
-                factor_source_kind
+                factor_source_kind,
             )
         })
     }
@@ -511,7 +511,7 @@ impl SecurityShieldBuilder {
     ) -> RoleBuilderMutateResult {
         self.get(|builder| {
             builder.validation_for_addition_of_factor_source_of_kind_to_primary_override(
-                factor_source_kind
+                factor_source_kind,
             )
         })
     }
@@ -690,14 +690,14 @@ impl SecurityShieldBuilder {
 
 impl SecurityShieldBuilder {
     /// `None` means valid!
-    pub fn validate(&self) -> Option<SecurityShieldBuilderInvalidReason> {
+    pub fn validate(&self) -> Option<SecurityShieldBuilderRuleViolation> {
         if DisplayName::new(self.get_name()).is_err() {
-            return Some(SecurityShieldBuilderInvalidReason::ShieldNameInvalid);
+            return Some(SecurityShieldBuilderRuleViolation::ShieldNameInvalid);
         }
 
         if self.get_authentication_signing_factor().is_none() {
             return Some(
-                SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor,
+                SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor,
             );
         }
 
@@ -714,7 +714,7 @@ impl SecurityShieldBuilder {
     /// Validates **just** the primary role **in isolation**.
     pub fn validate_primary_role(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         self.validate_role_in_isolation(RoleKind::Primary)
     }
 
@@ -722,7 +722,7 @@ impl SecurityShieldBuilder {
     pub fn validate_role_in_isolation(
         &self,
         role: RoleKind,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         self.get(|builder| {
             let validation = match role {
                 RoleKind::Primary => {
@@ -739,6 +739,47 @@ impl SecurityShieldBuilder {
         })
     }
 
+    pub fn is_role_in_isolation_invalid(&self, role: RoleKind) -> bool {
+        self.validate_role_in_isolation(role).is_some_and(|reason| {
+            matches!(
+                reason,
+                SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor |
+                SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor |
+                SecurityShieldBuilderRuleViolation::RecoveryRoleMustHaveAtLeastOneFactor |
+                SecurityShieldBuilderRuleViolation::ConfirmationRoleMustHaveAtLeastOneFactor
+            )
+        })
+    }
+
+    pub fn status(&self) -> SecurityShieldBuilderStatus {
+        let invalid_reason = SecurityShieldBuilderStatusInvalidReason::new(
+            IsPrimaryRoleFactorListEmpty(
+                self.is_role_in_isolation_invalid(RoleKind::Primary),
+            ),
+            IsRecoveryRoleFactorListEmpty(
+                self.is_role_in_isolation_invalid(RoleKind::Recovery),
+            ),
+            IsConfirmationRoleFactorListEmpty(
+                self.is_role_in_isolation_invalid(RoleKind::Confirmation),
+            ),
+            IsAuthSigningFactorMissing(
+                self.get_authentication_signing_factor().is_none(),
+            ),
+        );
+
+        if let Some(invalid_reason) = invalid_reason {
+            SecurityShieldBuilderStatus::Invalid {
+                reason: invalid_reason,
+            }
+        } else if let Some(rule_violation_reason) = self.validate() {
+            SecurityShieldBuilderStatus::Weak {
+                reason: rule_violation_reason,
+            }
+        } else {
+            SecurityShieldBuilderStatus::Strong
+        }
+    }
+
     pub fn selected_primary_threshold_factors_status(
         &self,
     ) -> SelectedPrimaryThresholdFactorsStatus {
@@ -750,10 +791,10 @@ impl SecurityShieldBuilder {
 
         if let Some(reason) = reason {
             return match reason {
-                SecurityShieldBuilderInvalidReason::PrimaryRoleMustHaveAtLeastOneFactor => {
+                SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor => {
                     SelectedPrimaryThresholdFactorsStatus::Insufficient
                 }
-                SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor => {
+                SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor => {
                     SelectedPrimaryThresholdFactorsStatus::Invalid {
                         reason: SelectedPrimaryThresholdFactorsStatusInvalidReason::CannotBeUsedAlone {
                             factor_source_kind: FactorSourceKind::Password,
@@ -801,11 +842,11 @@ impl SecurityShieldBuilder {
         &self,
     ) -> Result<
         SecurityStructureOfFactorSourceIds,
-        SecurityShieldBuilderInvalidReason,
+        SecurityShieldBuilderRuleViolation,
     > {
         let authentication_signing_factor =
             self.get_authentication_signing_factor().ok_or(
-                SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor,
+                SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor,
             )?;
         let matrix_result = self.get(|builder| builder.build());
 
@@ -821,7 +862,7 @@ impl SecurityShieldBuilder {
         let name = self.get_name();
         let display_name = DisplayName::new(name).map_err(|e| {
             error!("Invalid DisplayName {:?}", e);
-            SecurityShieldBuilderInvalidReason::ShieldNameInvalid
+            SecurityShieldBuilderRuleViolation::ShieldNameInvalid
         })?;
 
         let metadata = SecurityStructureMetadata::with_details(
@@ -1309,7 +1350,7 @@ mod tests {
             sut.selected_primary_threshold_factors_status(),
             SelectedPrimaryThresholdFactorsStatus::Invalid {
                 reason: SelectedPrimaryThresholdFactorsStatusInvalidReason::Other {
-                    underlying: SecurityShieldBuilderInvalidReason::PrimaryCannotHaveMultipleDevices
+                    underlying: SecurityShieldBuilderRuleViolation::PrimaryCannotHaveMultipleDevices
                 }
             }
         );
@@ -1342,7 +1383,7 @@ mod tests {
         pretty_assertions::assert_eq!(
             sut.validate(),
             Some(
-                SecurityShieldBuilderInvalidReason::FactorSourceAlreadyPresent
+                SecurityShieldBuilderRuleViolation::FactorSourceAlreadyPresent
             )
         );
         pretty_assertions::assert_eq!(
@@ -1390,7 +1431,7 @@ mod test_invalid {
         let sut = SUT::strict();
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
+            SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor
         );
     }
 
@@ -1409,7 +1450,7 @@ mod test_invalid {
 
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
+            SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor
         );
     }
 
@@ -1418,11 +1459,11 @@ mod test_invalid {
         let sut = SUT::sample_strict_with_auth_signing();
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Primary).unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor
         );
     }
 
@@ -1436,11 +1477,11 @@ mod test_invalid {
         sut.set_threshold(Threshold::zero());
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Primary).unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
         );
     }
 
@@ -1452,11 +1493,11 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::RecoveryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::RecoveryRoleMustHaveAtLeastOneFactor
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Recovery).unwrap(),
-            SecurityShieldBuilderInvalidReason::RecoveryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::RecoveryRoleMustHaveAtLeastOneFactor
         );
     }
 
@@ -1471,11 +1512,11 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::ConfirmationRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::ConfirmationRoleMustHaveAtLeastOneFactor
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Confirmation).unwrap(),
-            SecurityShieldBuilderInvalidReason::ConfirmationRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::ConfirmationRoleMustHaveAtLeastOneFactor
         );
     }
 
@@ -1493,7 +1534,7 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
+            SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor
         );
         assert!(sut.validate_role_in_isolation(RoleKind::Primary).is_none());
         sut.set_authentication_signing_factor(Some(
@@ -1541,7 +1582,7 @@ mod test_invalid {
         sut.set_name("");
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::ShieldNameInvalid
+            SecurityShieldBuilderRuleViolation::ShieldNameInvalid
         );
     }
 
@@ -1564,7 +1605,7 @@ mod test_invalid {
         sut.set_time_period_until_auto_confirm(TimePeriod::with_days(0));
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero
+            SecurityShieldBuilderRuleViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero
         );
     }
 
@@ -1582,7 +1623,7 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::RecoveryAndConfirmationFactorsOverlap
+            SecurityShieldBuilderRuleViolation::RecoveryAndConfirmationFactorsOverlap
         );
     }
 
@@ -1601,7 +1642,7 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole
+            SecurityShieldBuilderRuleViolation::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole
         );
     }
 
@@ -1620,7 +1661,7 @@ mod test_invalid {
         );
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole
+            SecurityShieldBuilderRuleViolation::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole
         );
     }
 
@@ -1646,11 +1687,11 @@ mod test_invalid {
 
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Primary).unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
         );
     }
 
@@ -1672,11 +1713,11 @@ mod test_invalid {
 
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Primary).unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
         );
     }
 
@@ -1701,7 +1742,7 @@ mod test_invalid {
 
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
         );
     }
 
@@ -1723,11 +1764,11 @@ mod test_invalid {
 
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor
         );
         assert_eq!(
             sut.validate_role_in_isolation(RoleKind::Primary).unwrap(),
-            SecurityShieldBuilderInvalidReason::PrimaryRoleMustHaveAtLeastOneFactor
+            SecurityShieldBuilderRuleViolation::PrimaryRoleMustHaveAtLeastOneFactor
         );
     }
 
@@ -1738,7 +1779,7 @@ mod test_invalid {
         sut.set_name("");
         assert_eq!(
             sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::ShieldNameInvalid
+            SecurityShieldBuilderRuleViolation::ShieldNameInvalid
         );
     }
 
@@ -1791,11 +1832,170 @@ mod test_invalid {
             status,
             SelectedPrimaryThresholdFactorsStatus::Invalid {
                 reason: Other {
-                    underlying: SecurityShieldBuilderInvalidReason::PrimaryCannotHaveMultipleDevices
+                    underlying: SecurityShieldBuilderRuleViolation::PrimaryCannotHaveMultipleDevices
                 }
             }
         );
     }
+
+    #[test]
+    fn shield_status_strong() {
+        let sut = SUT::default();
+
+        let _ = sut
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_device(),
+            )
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_password(),
+            )
+            .set_authentication_signing_factor(Some(
+                FactorSourceID::sample_device(),
+            ))
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_ledger(),
+            )
+            .add_factor_source_to_confirmation_override(
+                FactorSourceID::sample_arculus(),
+            );
+
+        let status = sut.status();
+
+        pretty_assertions::assert_eq!(
+            status,
+            SecurityShieldBuilderStatus::Strong
+        );
+        assert!(sut.build().is_ok())
+    }
+
+    #[test]
+    fn shield_status_weak() {
+        let sut = SUT::default();
+
+        let _ = sut
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_password(),
+            )
+            .set_authentication_signing_factor(Some(
+                FactorSourceID::sample_device(),
+            ))
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_ledger(),
+            )
+            .add_factor_source_to_confirmation_override(
+                FactorSourceID::sample_arculus(),
+            );
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+            }
+        );
+
+        let _ = sut
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_device(),
+            )
+            .remove_factor_from_recovery(FactorSourceID::sample_ledger())
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_arculus(),
+            );
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::RecoveryAndConfirmationFactorsOverlap
+            }
+        );
+
+        let _ = sut
+            .remove_factor_from_recovery(FactorSourceID::sample_password())
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_ledger_other(),
+            )
+            .add_factor_source_to_confirmation_override(
+                FactorSourceID::sample_ledger_other(),
+            );
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::RecoveryAndConfirmationFactorsOverlap
+            }
+        );
+        assert!(sut.build().is_ok())
+    }
+
+    #[test]
+    fn shield_status_invalid() {
+        let sut = SUT::default();
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Invalid {
+                reason: SecurityShieldBuilderStatusInvalidReason::new(
+                    IsPrimaryRoleFactorListEmpty(true),
+                    IsRecoveryRoleFactorListEmpty(true),
+                    IsConfirmationRoleFactorListEmpty(true),
+                    IsAuthSigningFactorMissing(true),
+                )
+                .unwrap()
+            }
+        );
+
+        let _ = sut.add_factor_source_to_primary_threshold(
+            FactorSourceID::sample_device(),
+        );
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Invalid {
+                reason: SecurityShieldBuilderStatusInvalidReason::new(
+                    IsPrimaryRoleFactorListEmpty(false),
+                    IsRecoveryRoleFactorListEmpty(true),
+                    IsConfirmationRoleFactorListEmpty(true),
+                    IsAuthSigningFactorMissing(true),
+                )
+                .unwrap()
+            }
+        );
+
+        let _ = sut.set_authentication_signing_factor(Some(
+            FactorSourceID::sample_device(),
+        ));
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Invalid {
+                reason: SecurityShieldBuilderStatusInvalidReason::new(
+                    IsPrimaryRoleFactorListEmpty(false),
+                    IsRecoveryRoleFactorListEmpty(true),
+                    IsConfirmationRoleFactorListEmpty(true),
+                    IsAuthSigningFactorMissing(false),
+                )
+                .unwrap()
+            }
+        );
+
+        let _ = sut.add_factor_source_to_recovery_override(
+            FactorSourceID::sample_ledger(),
+        );
+
+        pretty_assertions::assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Invalid {
+                reason: SecurityShieldBuilderStatusInvalidReason::new(
+                    IsPrimaryRoleFactorListEmpty(false),
+                    IsRecoveryRoleFactorListEmpty(false),
+                    IsConfirmationRoleFactorListEmpty(true),
+                    IsAuthSigningFactorMissing(false),
+                )
+                .unwrap()
+            }
+        );
+        assert!(sut.build().is_err())
+    }
 }
 
 #[cfg(test)]
@@ -1904,4 +2104,152 @@ mod lenient {
         test(FactorListKind::Threshold);
         test(FactorListKind::Override);
     }
+
+    #[test]
+    fn basic_validation() {
+        let sut = SUT::lenient();
+
+        let _ = sut
+            .set_authentication_signing_factor(Some(
+                FactorSourceID::sample_device(),
+            ))
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_device(),
+            )
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_device(),
+            ); // did not get added, duplicates are not allowed
+
+        assert_eq!(
+            sut.get_primary_threshold_factors(),
+            vec![FactorSourceID::sample_device()]
+        );
+
+        assert_eq!(
+            // Takes into consideration all the rules because it disregards the mode
+            // the builder was initialized with and always uses SecurityShieldBuilderMode::Strict
+            sut._validation_for_addition_of_factor_source_of_kind_to_primary_threshold(
+                FactorSourceKind::Device,
+            ),
+            Err(
+                RoleBuilderValidation::ForeverInvalid(
+                    ForeverInvalidReason::PrimaryCannotHaveMultipleDevices
+                )
+            )
+        );
+
+        let _ = sut.add_factor_source_to_primary_threshold(
+            FactorSourceID::sample_device_other(),
+        ); // actually this is added because of the lenient mode
+
+        assert_eq!(
+            sut.get_primary_threshold_factors(),
+            vec![
+                FactorSourceID::sample_device(),
+                FactorSourceID::sample_device_other()
+            ]
+        );
+
+        let _ = sut
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_ledger(),
+            )
+            .add_factor_source_to_confirmation_override(
+                FactorSourceID::sample_arculus(),
+            );
+
+        assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::PrimaryCannotHaveMultipleDevices
+            }
+        );
+        assert!(sut.build().is_ok());
+    }
+
+    #[test]
+    fn primary_password_never_alone() {
+        let sut = SUT::lenient();
+
+        let _ = sut
+            .set_authentication_signing_factor(FactorSourceID::sample_device())
+            .add_factor_source_to_primary_override(
+                FactorSourceID::sample_password(),
+            ); // not allowed
+
+        assert!(sut.get_primary_override_factors().is_empty(),);
+
+        let _ = sut
+            .add_factor_source_to_recovery_override(
+                FactorSourceID::sample_arculus(),
+            )
+            .add_factor_source_to_confirmation_override(
+                FactorSourceID::sample_arculus_other(),
+            )
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_password(),
+            );
+
+        assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+            }
+        );
+
+        let _ = sut
+            .add_factor_source_to_primary_threshold(
+                FactorSourceID::sample_ledger(),
+            )
+            .set_threshold(Threshold::Specific(1));
+
+        assert_eq!(
+            sut.status(),
+            SecurityShieldBuilderStatus::Weak {
+                reason: SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
+            }
+        );
+
+        let _ = sut.set_threshold(Threshold::Specific(2));
+
+        assert_eq!(sut.status(), SecurityShieldBuilderStatus::Strong);
+
+        let shield = sut.build().unwrap();
+        assert!(shield
+            .matrix_of_factors
+            .primary_role
+            .get_override_factors()
+            .is_empty());
+        assert_eq!(
+            shield.matrix_of_factors.primary_role.get_threshold(),
+            Threshold::Specific(2)
+        );
+        assert_eq!(
+            shield
+                .matrix_of_factors
+                .primary_role
+                .get_threshold_factors()
+                .clone(),
+            vec![
+                FactorSourceID::sample_password(),
+                FactorSourceID::sample_ledger()
+            ]
+        );
+    }
+
+    #[test]
+    fn validation_for_addition() {
+        let sut = SUT::lenient();
+
+        assert_eq!(
+            sut._validation_for_addition_of_factor_source_of_kind_to_primary_override(
+                FactorSourceKind::Password,
+            ),
+            Err(
+                RoleBuilderValidation::ForeverInvalid(
+                    ForeverInvalidReason::PrimaryCannotHavePasswordInOverrideList
+                )
+            )
+        );
+    }
 }
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_invalid_reason.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs
similarity index 80%
rename from crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_invalid_reason.rs
rename to crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs
index 0343284a0..fceab3cc0 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_invalid_reason.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_rule_violation.rs
@@ -3,7 +3,7 @@ use crate::prelude::*;
 pub trait AsShieldBuilderViolation {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason>;
+    ) -> Option<SecurityShieldBuilderRuleViolation>;
 }
 
 impl<T: std::fmt::Debug> AsShieldBuilderViolation
@@ -11,7 +11,7 @@ impl<T: std::fmt::Debug> AsShieldBuilderViolation
 {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         match self {
             Result::Err(err) => err.as_shield_validation(),
             Result::Ok(_) => None,
@@ -21,7 +21,7 @@ impl<T: std::fmt::Debug> AsShieldBuilderViolation
 impl AsShieldBuilderViolation for MatrixBuilderValidation {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         match self {
             MatrixBuilderValidation::RoleInIsolation { role, violation } => {
                 (*role, *violation).as_shield_validation()
@@ -36,7 +36,7 @@ impl AsShieldBuilderViolation for MatrixBuilderValidation {
 impl AsShieldBuilderViolation for MatrixRolesInCombinationViolation {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         match self {
             Self::Basic(val) => val.as_shield_validation(),
             Self::ForeverInvalid(val) => val.as_shield_validation(),
@@ -48,13 +48,13 @@ impl AsShieldBuilderViolation for MatrixRolesInCombinationViolation {
 impl AsShieldBuilderViolation for MatrixRolesInCombinationBasicViolation {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         use MatrixRolesInCombinationBasicViolation::*;
         match self {
             FactorSourceNotFoundInAnyRole =>
                 unreachable!("Cannot happen since this error is not returned by 'validate'/'build'."),
             NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero => {
-                Some(SecurityShieldBuilderInvalidReason::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero)
+                Some(SecurityShieldBuilderRuleViolation::NumberOfDaysUntilAutoConfirmMustBeGreaterThanZero)
             }
         }
     }
@@ -62,11 +62,11 @@ impl AsShieldBuilderViolation for MatrixRolesInCombinationBasicViolation {
 impl AsShieldBuilderViolation for MatrixRolesInCombinationForeverInvalid {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         use MatrixRolesInCombinationForeverInvalid::*;
         match self {
             RecoveryAndConfirmationFactorsOverlap => {
-                Some(SecurityShieldBuilderInvalidReason::RecoveryAndConfirmationFactorsOverlap)
+                Some(SecurityShieldBuilderRuleViolation::RecoveryAndConfirmationFactorsOverlap)
             }
         }
     }
@@ -74,12 +74,12 @@ impl AsShieldBuilderViolation for MatrixRolesInCombinationForeverInvalid {
 impl AsShieldBuilderViolation for MatrixRolesInCombinationNotYetValid {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         use MatrixRolesInCombinationNotYetValid::*;
 
         match self {
             SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole => {
-                Some(SecurityShieldBuilderInvalidReason::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole)
+                Some(SecurityShieldBuilderRuleViolation::SingleFactorUsedInPrimaryMustNotBeUsedInAnyOtherRole)
             }
         }
     }
@@ -88,7 +88,7 @@ impl AsShieldBuilderViolation for MatrixRolesInCombinationNotYetValid {
 impl AsShieldBuilderViolation for (RoleKind, RoleBuilderValidation) {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         let (role_kind, violation) = self;
         match violation {
             RoleBuilderValidation::BasicViolation(basic) => unreachable!("Programmer error. Should have prevented this from happening: '{:?}'", basic),
@@ -105,37 +105,37 @@ impl AsShieldBuilderViolation for (RoleKind, RoleBuilderValidation) {
 impl AsShieldBuilderViolation for ForeverInvalidReason {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         use ForeverInvalidReason::*;
         let reason = match self {
-            FactorSourceAlreadyPresent => SecurityShieldBuilderInvalidReason::FactorSourceAlreadyPresent,
+            FactorSourceAlreadyPresent => SecurityShieldBuilderRuleViolation::FactorSourceAlreadyPresent,
             PrimaryCannotHaveMultipleDevices => {
-                SecurityShieldBuilderInvalidReason::PrimaryCannotHaveMultipleDevices
+                SecurityShieldBuilderRuleViolation::PrimaryCannotHaveMultipleDevices
             }
             PrimaryCannotHavePasswordInOverrideList => {
-                SecurityShieldBuilderInvalidReason::PrimaryCannotHavePasswordInOverrideList
+                SecurityShieldBuilderRuleViolation::PrimaryCannotHavePasswordInOverrideList
             }
             PrimaryCannotContainSecurityQuestions => {
-                SecurityShieldBuilderInvalidReason::PrimaryCannotContainSecurityQuestions
+                SecurityShieldBuilderRuleViolation::PrimaryCannotContainSecurityQuestions
             }
             PrimaryCannotContainTrustedContact => {
-                SecurityShieldBuilderInvalidReason::PrimaryCannotContainTrustedContact
+                SecurityShieldBuilderRuleViolation::PrimaryCannotContainTrustedContact
             }
             RecoveryRoleSecurityQuestionsNotSupported => {
-                SecurityShieldBuilderInvalidReason::RecoveryRoleSecurityQuestionsNotSupported
+                SecurityShieldBuilderRuleViolation::RecoveryRoleSecurityQuestionsNotSupported
             }
             RecoveryRolePasswordNotSupported => {
-                SecurityShieldBuilderInvalidReason::RecoveryRolePasswordNotSupported
+                SecurityShieldBuilderRuleViolation::RecoveryRolePasswordNotSupported
             }
             ConfirmationRoleTrustedContactNotSupported => {
-                SecurityShieldBuilderInvalidReason::ConfirmationRoleTrustedContactNotSupported
+                SecurityShieldBuilderRuleViolation::ConfirmationRoleTrustedContactNotSupported
             }
         };
         Some(reason)
     }
 }
 
-impl SecurityShieldBuilderInvalidReason {
+impl SecurityShieldBuilderRuleViolation {
     pub(crate) fn role_must_have_at_least_one_factor(
         role_kind: &RoleKind,
     ) -> Self {
@@ -152,33 +152,31 @@ impl SecurityShieldBuilderInvalidReason {
 impl AsShieldBuilderViolation for (RoleKind, NotYetValidReason) {
     fn as_shield_validation(
         &self,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         let (role_kind, violation) = self;
         use NotYetValidReason::*;
         let reason = match violation {
-            RoleMustHaveAtLeastOneFactor => SecurityShieldBuilderInvalidReason::role_must_have_at_least_one_factor(role_kind),
+            RoleMustHaveAtLeastOneFactor => SecurityShieldBuilderRuleViolation::role_must_have_at_least_one_factor(role_kind),
             PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor => {
-                SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
+                SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustHaveAnotherFactor
             }
             PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero => {
-                SecurityShieldBuilderInvalidReason::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
+                SecurityShieldBuilderRuleViolation::PrimaryRoleWithThresholdFactorsCannotHaveAThresholdValueOfZero
             }
             PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne => {
-                SecurityShieldBuilderInvalidReason::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
+                SecurityShieldBuilderRuleViolation::PrimaryRoleWithPasswordInThresholdListMustThresholdGreaterThanOne
             }
             ThresholdHigherThanThresholdFactorsLen => {
-                SecurityShieldBuilderInvalidReason::ThresholdHigherThanThresholdFactorsLen
+                SecurityShieldBuilderRuleViolation::ThresholdHigherThanThresholdFactorsLen
             }
         };
         Some(reason)
     }
 }
 
-// #[derive(Clone, Debug, PartialEq, Eq, thiserror::Error)]
-
 #[repr(u32)]
 #[derive(Clone, Debug, thiserror::Error, PartialEq)]
-pub enum SecurityShieldBuilderInvalidReason {
+pub enum SecurityShieldBuilderRuleViolation {
     #[error("Auth Signing Factor Missing")]
     MissingAuthSigningFactor,
 
@@ -250,13 +248,13 @@ pub enum SecurityShieldBuilderInvalidReason {
     ConfirmationRoleTrustedContactNotSupported,
 }
 
-impl HasSampleValues for SecurityShieldBuilderInvalidReason {
+impl HasSampleValues for SecurityShieldBuilderRuleViolation {
     fn sample() -> Self {
-        SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
+        SecurityShieldBuilderRuleViolation::MissingAuthSigningFactor
     }
 
     fn sample_other() -> Self {
-        SecurityShieldBuilderInvalidReason::ShieldNameInvalid
+        SecurityShieldBuilderRuleViolation::ShieldNameInvalid
     }
 }
 
@@ -265,7 +263,7 @@ mod tests {
     use super::*;
 
     #[allow(clippy::upper_case_acronyms)]
-    type SUT = SecurityShieldBuilderInvalidReason;
+    type SUT = SecurityShieldBuilderRuleViolation;
 
     #[test]
     fn equality() {
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_status.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_status.rs
new file mode 100644
index 000000000..c08646711
--- /dev/null
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/security_shield_builder_status.rs
@@ -0,0 +1,165 @@
+use core_misc::decl_bool_type;
+use std::ops::Not;
+
+use crate::prelude::*;
+
+/// Represents the status of `SecurityShieldBuilder`.
+/// Used for UI representation in host applications.
+#[derive(Clone, Debug, PartialEq)]
+pub enum SecurityShieldBuilderStatus {
+    /// The selected factor sources form a strong combination
+    /// in the Security Shield building process.
+    Strong,
+
+    /// The selected factor sources form a weak combination
+    /// in the Security Shield building process.
+    Weak {
+        /// The reason why the built shield would be weak.
+        reason: SecurityShieldBuilderRuleViolation,
+    },
+
+    /// The selected factor sources form an invalid combination
+    /// in the Security Shield building process.
+    /// Example: Each role must have at least one factor.
+    Invalid {
+        reason: SecurityShieldBuilderStatusInvalidReason,
+    },
+}
+
+impl HasSampleValues for SecurityShieldBuilderStatus {
+    fn sample() -> Self {
+        SecurityShieldBuilderStatus::Strong
+    }
+
+    fn sample_other() -> Self {
+        SecurityShieldBuilderStatus::Weak {
+            reason: SecurityShieldBuilderRuleViolation::RecoveryAndConfirmationFactorsOverlap
+        }
+    }
+}
+
+decl_bool_type!(IsPrimaryRoleFactorListEmpty, false);
+decl_bool_type!(IsRecoveryRoleFactorListEmpty, false);
+decl_bool_type!(IsConfirmationRoleFactorListEmpty, false);
+decl_bool_type!(IsAuthSigningFactorMissing, false);
+
+/// Represents the reason why the `SecurityShieldBuilder` has an invalid status.
+/// This struct contains the specific reasons for each component of the security shield builder
+/// being invalid. The components include:
+/// - Primary role
+/// - Recovery role
+/// - Confirmation role
+/// - Authentication signing
+#[derive(Clone, Debug, PartialEq)]
+pub struct SecurityShieldBuilderStatusInvalidReason {
+    pub is_primary_role_factor_list_empty: IsPrimaryRoleFactorListEmpty,
+    pub is_recovery_role_factor_list_empty: IsRecoveryRoleFactorListEmpty,
+    pub is_confirmation_role_factor_list_empty:
+        IsConfirmationRoleFactorListEmpty,
+    pub is_auth_signing_factor_missing: IsAuthSigningFactorMissing,
+}
+
+impl SecurityShieldBuilderStatusInvalidReason {
+    pub fn new(
+        is_primary_role_factor_list_empty: IsPrimaryRoleFactorListEmpty,
+        is_recovery_role_factor_list_empty: IsRecoveryRoleFactorListEmpty,
+        is_confirmation_role_factor_list_empty: IsConfirmationRoleFactorListEmpty,
+        is_auth_signing_factor_missing: IsAuthSigningFactorMissing,
+    ) -> Option<Self> {
+        if is_primary_role_factor_list_empty.not()
+            && is_recovery_role_factor_list_empty.not()
+            && is_confirmation_role_factor_list_empty.not()
+            && is_auth_signing_factor_missing.not()
+        {
+            return None;
+        }
+
+        Some(Self {
+            is_primary_role_factor_list_empty,
+            is_recovery_role_factor_list_empty,
+            is_confirmation_role_factor_list_empty,
+            is_auth_signing_factor_missing,
+        })
+    }
+}
+
+impl HasSampleValues for SecurityShieldBuilderStatusInvalidReason {
+    fn sample() -> Self {
+        SecurityShieldBuilderStatusInvalidReason::new(
+            IsPrimaryRoleFactorListEmpty(true),
+            IsRecoveryRoleFactorListEmpty::default(),
+            IsConfirmationRoleFactorListEmpty::default(),
+            IsAuthSigningFactorMissing::default(),
+        )
+        .unwrap()
+    }
+
+    fn sample_other() -> Self {
+        SecurityShieldBuilderStatusInvalidReason::new(
+            IsPrimaryRoleFactorListEmpty::default(),
+            IsRecoveryRoleFactorListEmpty(true),
+            IsConfirmationRoleFactorListEmpty(true),
+            IsAuthSigningFactorMissing::default(),
+        )
+        .unwrap()
+    }
+}
+
+#[cfg(test)]
+mod status_tests {
+    use super::*;
+
+    #[allow(clippy::upper_case_acronyms)]
+    type SUT = SecurityShieldBuilderStatus;
+
+    #[test]
+    fn equality() {
+        assert_eq!(SUT::sample(), SUT::sample());
+        assert_eq!(SUT::sample_other(), SUT::sample_other());
+    }
+
+    #[test]
+    fn inequality() {
+        assert_ne!(SUT::sample(), SUT::sample_other());
+    }
+}
+
+#[cfg(test)]
+mod reason_tests {
+    use super::*;
+
+    #[allow(clippy::upper_case_acronyms)]
+    type SUT = SecurityShieldBuilderStatusInvalidReason;
+
+    #[test]
+    fn equality() {
+        assert_eq!(SUT::sample(), SUT::sample());
+        assert_eq!(SUT::sample_other(), SUT::sample_other());
+    }
+
+    #[test]
+    fn inequality() {
+        assert_ne!(SUT::sample(), SUT::sample_other());
+    }
+
+    #[test]
+    fn new() {
+        let invalid_reason = SecurityShieldBuilderStatusInvalidReason::new(
+            IsPrimaryRoleFactorListEmpty::default(),
+            IsRecoveryRoleFactorListEmpty::default(),
+            IsConfirmationRoleFactorListEmpty::default(),
+            IsAuthSigningFactorMissing::default(),
+        );
+
+        assert!(invalid_reason.is_none());
+
+        let invalid_reason = SecurityShieldBuilderStatusInvalidReason::new(
+            IsPrimaryRoleFactorListEmpty(true),
+            IsRecoveryRoleFactorListEmpty::default(),
+            IsConfirmationRoleFactorListEmpty::default(),
+            IsAuthSigningFactorMissing::default(),
+        );
+
+        assert!(invalid_reason.is_some());
+    }
+}
diff --git a/crates/profile/models/security-structures/src/roles_matrices_structures/selected_primary_threshold_factors_status.rs b/crates/profile/models/security-structures/src/roles_matrices_structures/selected_primary_threshold_factors_status.rs
index 7c2dbbecf..6effd04e5 100644
--- a/crates/profile/models/security-structures/src/roles_matrices_structures/selected_primary_threshold_factors_status.rs
+++ b/crates/profile/models/security-structures/src/roles_matrices_structures/selected_primary_threshold_factors_status.rs
@@ -36,7 +36,7 @@ pub enum SelectedPrimaryThresholdFactorsStatusInvalidReason {
         factor_source_kind: FactorSourceKind,
     },
     Other {
-        underlying: SecurityShieldBuilderInvalidReason,
+        underlying: SecurityShieldBuilderRuleViolation,
     },
 }
 
@@ -49,7 +49,7 @@ impl HasSampleValues for SelectedPrimaryThresholdFactorsStatusInvalidReason {
 
     fn sample_other() -> Self {
         SelectedPrimaryThresholdFactorsStatusInvalidReason::Other {
-            underlying: SecurityShieldBuilderInvalidReason::PrimaryCannotHaveMultipleDevices,
+            underlying: SecurityShieldBuilderRuleViolation::PrimaryCannotHaveMultipleDevices,
         }
     }
 }
diff --git a/crates/profile/models/security-structures/src/threshold.rs b/crates/profile/models/security-structures/src/threshold.rs
index 1769ebe8c..ce84a8ffe 100644
--- a/crates/profile/models/security-structures/src/threshold.rs
+++ b/crates/profile/models/security-structures/src/threshold.rs
@@ -27,7 +27,11 @@ impl Threshold {
     /// Returns the selectable values for a threshold.
     pub fn values(max_threshold: u8) -> Vec<Threshold> {
         std::iter::once(Threshold::All)
-            .chain((1..=max_threshold - 1).rev().map(Threshold::Specific))
+            .chain(
+                (1..=max_threshold.saturating_sub(1))
+                    .rev()
+                    .map(Threshold::Specific),
+            )
             .collect()
     }
 }
@@ -78,5 +82,8 @@ mod tests {
     fn values() {
         let res = SUT::values(3);
         assert_eq!(res, vec![SUT::All, SUT::Specific(2), SUT::Specific(1)]);
+
+        let res = SUT::values(0);
+        assert_eq!(res, vec![SUT::All]);
     }
 }
diff --git a/crates/profile/models/security-structures/src/time_period.rs b/crates/profile/models/security-structures/src/time_period.rs
index 4da860f68..fc1e81b27 100644
--- a/crates/profile/models/security-structures/src/time_period.rs
+++ b/crates/profile/models/security-structures/src/time_period.rs
@@ -11,12 +11,7 @@ pub struct TimePeriod {
 
 impl TimePeriod {
     pub fn with_days(value: u16) -> Self {
-        if (value % DAYS_PER_YEAR) == 0 {
-            Self {
-                value: value / DAYS_PER_YEAR,
-                unit: TimePeriodUnit::Years,
-            }
-        } else if (value % DAYS_PER_WEEK) == 0 {
+        if (value % DAYS_PER_WEEK) == 0 {
             Self {
                 value: value / DAYS_PER_WEEK,
                 unit: TimePeriodUnit::Weeks,
@@ -33,7 +28,6 @@ impl TimePeriod {
         match self.unit {
             TimePeriodUnit::Days => self.value,
             TimePeriodUnit::Weeks => self.value * DAYS_PER_WEEK,
-            TimePeriodUnit::Years => self.value * DAYS_PER_YEAR,
         }
     }
 }
@@ -74,17 +68,7 @@ mod tests {
 
     #[test]
     fn days_conversion() {
-        let mut sut = SUT::with_days(DAYS_PER_YEAR);
-        assert_eq!(sut.days(), DAYS_PER_YEAR);
-        assert_eq!(sut.value, 1);
-        assert_eq!(sut.unit, TimePeriodUnit::Years);
-
-        sut = SUT::with_days(1095);
-        assert_eq!(sut.days(), 1095);
-        assert_eq!(sut.value, 3);
-        assert_eq!(sut.unit, TimePeriodUnit::Years);
-
-        sut = SUT::with_days(DAYS_PER_WEEK);
+        let mut sut = SUT::with_days(DAYS_PER_WEEK);
         assert_eq!(sut.days(), DAYS_PER_WEEK);
         assert_eq!(sut.value, 1);
         assert_eq!(sut.unit, TimePeriodUnit::Weeks);
diff --git a/crates/profile/models/security-structures/src/time_period_unit.rs b/crates/profile/models/security-structures/src/time_period_unit.rs
index 12d34d177..4232ed9a5 100644
--- a/crates/profile/models/security-structures/src/time_period_unit.rs
+++ b/crates/profile/models/security-structures/src/time_period_unit.rs
@@ -7,7 +7,6 @@ use crate::prelude::*;
 pub enum TimePeriodUnit {
     Days,
     Weeks,
-    Years,
 }
 
 impl HasSampleValues for TimePeriodUnit {
diff --git a/crates/profile/models/supporting-types/Cargo.toml b/crates/profile/models/supporting-types/Cargo.toml
index fffa90954..64ccd85cc 100644
--- a/crates/profile/models/supporting-types/Cargo.toml
+++ b/crates/profile/models/supporting-types/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-supporting-types"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/profile/traits/entity-by-address/Cargo.toml b/crates/profile/traits/entity-by-address/Cargo.toml
index b2a08ac6e..6f45a8ba5 100644
--- a/crates/profile/traits/entity-by-address/Cargo.toml
+++ b/crates/profile/traits/entity-by-address/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "entity-by-address"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/sargon/Cargo.toml b/crates/sargon/Cargo.toml
index a850a7f52..4b6e6c6e5 100644
--- a/crates/sargon/Cargo.toml
+++ b/crates/sargon/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 resolver = "2" # features enabled in integration test
diff --git a/crates/system/clients/clients/Cargo.toml b/crates/system/clients/clients/Cargo.toml
index cb705272e..75532ec8e 100644
--- a/crates/system/clients/clients/Cargo.toml
+++ b/crates/system/clients/clients/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clients"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/system/clients/http/Cargo.toml b/crates/system/clients/http/Cargo.toml
index 1878d1308..476b3ea68 100644
--- a/crates/system/clients/http/Cargo.toml
+++ b/crates/system/clients/http/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "http-client"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/drivers/Cargo.toml b/crates/system/drivers/Cargo.toml
index 099b47978..33eec3c42 100644
--- a/crates/system/drivers/Cargo.toml
+++ b/crates/system/drivers/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "drivers"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/system/interactors/Cargo.toml b/crates/system/interactors/Cargo.toml
index 61490c10e..ca20538ea 100644
--- a/crates/system/interactors/Cargo.toml
+++ b/crates/system/interactors/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "interactors"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/accounts/Cargo.toml b/crates/system/os/accounts/Cargo.toml
index c9ad805bf..a00b67434 100644
--- a/crates/system/os/accounts/Cargo.toml
+++ b/crates/system/os/accounts/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os-accounts"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/factors/Cargo.toml b/crates/system/os/factors/Cargo.toml
index 3ba57b77d..fe75615cd 100644
--- a/crates/system/os/factors/Cargo.toml
+++ b/crates/system/os/factors/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os-factors"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/factors/src/sargon_os_security_structures.rs b/crates/system/os/factors/src/sargon_os_security_structures.rs
index 5d0937460..5117eaf6e 100644
--- a/crates/system/os/factors/src/sargon_os_security_structures.rs
+++ b/crates/system/os/factors/src/sargon_os_security_structures.rs
@@ -34,7 +34,7 @@ pub trait OsSecurityStructuresQuerying {
     async fn add_security_structure_of_factor_source_ids(
         &self,
         structure_ids: &SecurityStructureOfFactorSourceIDs,
-    ) -> Result<bool>;
+    ) -> Result<()>;
 }
 
 #[async_trait::async_trait]
@@ -97,7 +97,7 @@ impl OsSecurityStructuresQuerying for SargonOS {
     /// If `structure` references a FactorSource by ID which is unknown to Profile,
     /// `Err(CommonError::StructureReferencesUnknownFactorSource)` is returned.
     ///
-    /// If Profile already contains a structure with the same ID, `Ok(false)` is
+    /// If Profile already contains a structure with the same ID, `Err(CommonError::)` is
     /// returned **without** modifying the existing one.
     ///
     /// # Emits Events
@@ -108,7 +108,7 @@ impl OsSecurityStructuresQuerying for SargonOS {
     async fn add_security_structure_of_factor_source_ids(
         &self,
         structure_ids: &SecurityStructureOfFactorSourceIDs,
-    ) -> Result<bool> {
+    ) -> Result<()> {
         let id = structure_ids.metadata.id;
         let ids_of_factors_in_profile = self.factor_source_ids()?;
         let ids_in_structure = structure_ids
@@ -139,14 +139,18 @@ impl OsSecurityStructuresQuerying for SargonOS {
             })
             .await?;
 
-        if inserted {
-            self.event_bus
-                .emit(EventNotification::profile_modified(
-                    EventProfileModified::SecurityStructureAdded { id },
-                ))
-                .await;
+        if !inserted {
+            return Err(CommonError::StructureAlreadyExists {
+                bad_value: id.to_string(),
+            });
         }
-        Ok(inserted)
+
+        self.event_bus
+            .emit(EventNotification::profile_modified(
+                EventProfileModified::SecurityStructureAdded { id },
+            ))
+            .await;
+        Ok(())
     }
 }
 
@@ -217,7 +221,7 @@ mod tests {
         // ACT
         let structure_factor_id_level =
             SecurityStructureOfFactorSourceIDs::sample();
-        let inserted = os
+        let _ = os
             .with_timeout(|x| {
                 x.add_security_structure_of_factor_source_ids(
                     &structure_factor_id_level,
@@ -227,7 +231,6 @@ mod tests {
             .unwrap();
 
         // ASSERT
-        assert!(inserted);
         assert!(os
             .profile()
             .unwrap()
@@ -319,7 +322,7 @@ mod tests {
         // ACT
         let structure_ids = SecurityStructureOfFactorSourceIDs::sample();
         let id = structure_ids.metadata.id;
-        let inserted = os
+        let _ = os
             .with_timeout(|x| {
                 x.add_security_structure_of_factor_source_ids(&structure_ids)
             })
@@ -327,7 +330,6 @@ mod tests {
             .unwrap();
 
         // ASSERT
-        assert!(inserted);
         assert!(event_bus_driver.recorded().iter().any(|e| e.event
             == Event::ProfileModified {
                 change: EventProfileModified::SecurityStructureAdded { id }
@@ -348,7 +350,7 @@ mod tests {
             SecurityStructureOfFactorSourceIDs::sample();
         let structure_source_ids_sample_other =
             SecurityStructureOfFactorSourceIDs::sample_other();
-        let inserted = os
+        let _ = os
             .with_timeout(|x| {
                 x.add_security_structure_of_factor_source_ids(
                     &structure_source_ids_sample,
@@ -356,9 +358,22 @@ mod tests {
             })
             .await
             .unwrap();
-        assert!(inserted);
 
-        let inserted = os
+        let result = os
+            .with_timeout(|x| {
+                x.add_security_structure_of_factor_source_ids(
+                    &structure_source_ids_sample,
+                )
+            })
+            .await;
+        assert_eq!(
+            result,
+            Err(CommonError::StructureAlreadyExists {
+                bad_value: structure_source_ids_sample.metadata.id.to_string()
+            })
+        );
+
+        let _ = os
             .with_timeout(|x| {
                 x.add_security_structure_of_factor_source_ids(
                     &structure_source_ids_sample_other,
@@ -366,7 +381,6 @@ mod tests {
             })
             .await
             .unwrap();
-        assert!(inserted);
 
         let structure_id_sample = SecurityStructureOfFactorSourceIDs::from(
             structure_source_ids_sample.clone(),
diff --git a/crates/system/os/os/Cargo.toml b/crates/system/os/os/Cargo.toml
index dd32d9198..273ab794a 100644
--- a/crates/system/os/os/Cargo.toml
+++ b/crates/system/os/os/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/security-center/Cargo.toml b/crates/system/os/security-center/Cargo.toml
index cb8366184..fb7a6f73b 100644
--- a/crates/system/os/security-center/Cargo.toml
+++ b/crates/system/os/security-center/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os-security-center"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/signing/Cargo.toml b/crates/system/os/signing/Cargo.toml
index 7b10495ec..dfa1138c4 100644
--- a/crates/system/os/signing/Cargo.toml
+++ b/crates/system/os/signing/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os-signing"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/os/transaction/Cargo.toml b/crates/system/os/transaction/Cargo.toml
index 34b78845e..339fee854 100644
--- a/crates/system/os/transaction/Cargo.toml
+++ b/crates/system/os/transaction/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-os-transaction"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/profile-state-holder/Cargo.toml b/crates/system/profile-state-holder/Cargo.toml
index 59dc46744..f398c37f7 100644
--- a/crates/system/profile-state-holder/Cargo.toml
+++ b/crates/system/profile-state-holder/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "profile-state-holder"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/system/sub-systems/Cargo.toml b/crates/system/sub-systems/Cargo.toml
index 899e082a1..569aeb37a 100644
--- a/crates/system/sub-systems/Cargo.toml
+++ b/crates/system/sub-systems/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sub-systems"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/transaction/foundation/Cargo.toml b/crates/transaction/foundation/Cargo.toml
index d1e30dedc..3c9352dfa 100644
--- a/crates/transaction/foundation/Cargo.toml
+++ b/crates/transaction/foundation/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "transaction-foundation"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/transaction/manifests/Cargo.toml b/crates/transaction/manifests/Cargo.toml
index c1cb3146e..765e55948 100644
--- a/crates/transaction/manifests/Cargo.toml
+++ b/crates/transaction/manifests/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "manifests"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/transaction/models/Cargo.toml b/crates/transaction/models/Cargo.toml
index 97c1e5a2b..8f594a363 100644
--- a/crates/transaction/models/Cargo.toml
+++ b/crates/transaction/models/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "transaction-models"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 
diff --git a/crates/uniffi/conversion-macros/Cargo.toml b/crates/uniffi/conversion-macros/Cargo.toml
index 7854a0219..233b5505e 100644
--- a/crates/uniffi/conversion-macros/Cargo.toml
+++ b/crates/uniffi/conversion-macros/Cargo.toml
@@ -1,7 +1,7 @@
 
 [package]
 name = "sargon-uniffi-conversion-macros"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 
 [dependencies]
diff --git a/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml b/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml
index 66bb23381..0241262d5 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml
+++ b/crates/uniffi/uniffi_SPLIT_ME/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "sargon-uniffi"
-version = "1.1.112"
+version = "1.1.113"
 edition = "2021"
 build = "build.rs"
 
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/core/error/common_error.rs b/crates/uniffi/uniffi_SPLIT_ME/src/core/error/common_error.rs
index 55cb29acd..35f9627cc 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/core/error/common_error.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/core/error/common_error.rs
@@ -102,6 +102,12 @@ pub enum CommonError {
         bad_value: String,
     },
     SigningFailedTooManyFactorSourcesNeglected,
+    GatewaySubmitDuplicateTX {
+        intent_hash: String,
+    },
+    UnableToLoadMnemonicFromSecureStorage {
+        bad_value: String,
+    },
 }
 
 #[uniffi::export]
@@ -307,6 +313,16 @@ impl CommonError {
             SigningFailedTooManyFactorSourcesNeglected => {
                 InternalCommonError::SigningFailedTooManyFactorSourcesNeglected
             }
+            GatewaySubmitDuplicateTX { intent_hash } => {
+                InternalCommonError::GatewaySubmitDuplicateTX {
+                    intent_hash: intent_hash.clone(),
+                }
+            }
+            UnableToLoadMnemonicFromSecureStorage { bad_value } => {
+                InternalCommonError::UnableToLoadMnemonicFromSecureStorage {
+                    bad_value: bad_value.clone(),
+                }
+            }
             _ => InternalCommonError::Unknown,
         }
     }
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/mod.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/mod.rs
index 8bb95fd1e..47c24732a 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/mod.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/mod.rs
@@ -2,7 +2,8 @@ mod matrices;
 mod models;
 mod roles;
 mod security_shield_builder;
-mod security_shield_builder_invalid_reason;
+mod security_shield_builder_rule_violation;
+mod security_shield_builder_status;
 mod security_shield_prerequisites_status;
 mod security_structure_id;
 mod security_structure_metadata;
@@ -12,7 +13,8 @@ mod selected_primary_threshold_factors_status;
 pub use matrices::*;
 pub use models::*;
 pub use roles::*;
-pub use security_shield_builder_invalid_reason::*;
+pub use security_shield_builder_rule_violation::*;
+pub use security_shield_builder_status::*;
 pub use security_shield_prerequisites_status::*;
 pub use security_structure_id::*;
 pub use security_structure_metadata::*;
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/factor_source_in_role_builder_validation_status.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/factor_source_in_role_builder_validation_status.rs
index f00dabf0f..49badeaac 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/factor_source_in_role_builder_validation_status.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/factor_source_in_role_builder_validation_status.rs
@@ -16,7 +16,7 @@ pub struct FactorSourceValidationStatus {
 #[derive(Clone, Debug, PartialEq, uniffi::Enum)]
 pub enum FactorSourceValidationStatusReasonIfInvalid {
     BasicViolation(String),
-    NonBasic(SecurityShieldBuilderInvalidReason),
+    NonBasic(SecurityShieldBuilderRuleViolation),
 }
 
 impl From<sargon::FactorSourceInRoleBuilderValidationStatus>
@@ -35,7 +35,7 @@ impl From<sargon::FactorSourceInRoleBuilderValidationStatus>
                 ),
                 Err(sargon::RoleBuilderValidation::ForeverInvalid(v)) => v
                     .as_shield_validation()
-                    .map(SecurityShieldBuilderInvalidReason::from)
+                    .map(SecurityShieldBuilderRuleViolation::from)
                     .map(|x| {
                         FactorSourceValidationStatusReasonIfInvalid::NonBasic(x)
                     }),
@@ -43,7 +43,7 @@ impl From<sargon::FactorSourceInRoleBuilderValidationStatus>
                     val.role, v,
                 )
                     .as_shield_validation()
-                    .map(SecurityShieldBuilderInvalidReason::from)
+                    .map(SecurityShieldBuilderRuleViolation::from)
                     .map(|x| {
                         FactorSourceValidationStatusReasonIfInvalid::NonBasic(x)
                     }),
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period_unit.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period_unit.rs
index 7a91bd6a1..11bd28a0a 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period_unit.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/models/time_period_unit.rs
@@ -9,5 +9,4 @@ use sargon::TimePeriodUnit as InternalTimePeriodUnit;
 pub enum TimePeriodUnit {
     Days,
     Weeks,
-    Years,
 }
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs
index 3f8bad36e..c80a19c99 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder.rs
@@ -457,14 +457,10 @@ impl SecurityShieldBuilder {
 
 #[uniffi::export]
 impl SecurityShieldBuilder {
-    pub fn validate(&self) -> Option<SecurityShieldBuilderInvalidReason> {
-        self.get(|builder| builder.validate().map(|x| x.into()))
-    }
-
     pub fn validate_role_in_isolation(
         &self,
         role: RoleKind,
-    ) -> Option<SecurityShieldBuilderInvalidReason> {
+    ) -> Option<SecurityShieldBuilderRuleViolation> {
         self.get(|builder| {
             builder
                 .validate_role_in_isolation(role.into_internal())
@@ -472,6 +468,10 @@ impl SecurityShieldBuilder {
         })
     }
 
+    pub fn status(&self) -> SecurityShieldBuilderStatus {
+        self.get(|builder| builder.status().into())
+    }
+
     pub fn selected_primary_threshold_factors_status(
         &self,
     ) -> SelectedPrimaryThresholdFactorsStatus {
@@ -497,7 +497,7 @@ impl SecurityShieldBuilder {
         &self,
     ) -> Result<
         SecurityStructureOfFactorSourceIDs,
-        SecurityShieldBuilderInvalidReason,
+        SecurityShieldBuilderRuleViolation,
     > {
         self.get(|builder| builder.build())
             .map(|shield| shield.into())
@@ -906,8 +906,16 @@ mod tests {
         assert_eq!(xs, sut.clone().get_confirmation_factors());
 
         assert_eq!(
-            sut.validate().unwrap(),
-            SecurityShieldBuilderInvalidReason::MissingAuthSigningFactor
+            sut.status(),
+            SecurityShieldBuilderStatus::Invalid {
+                reason: SecurityShieldBuilderStatusInvalidReason {
+                    is_primary_role_factor_list_empty: false,
+                    is_recovery_role_factor_list_empty: false,
+                    is_confirmation_role_factor_list_empty: false,
+                    is_auth_signing_factor_missing: true
+                }
+            }
+            .into()
         );
         sut = sut.set_authentication_signing_factor(Some(
             FactorSourceID::sample_device_other(),
@@ -917,9 +925,9 @@ mod tests {
             Some(FactorSourceID::sample_device_other())
         );
 
-        let v0 = sut.validate();
-        let v1 = sut.validate(); // can call validate many times!
-        assert_eq!(v0, v1);
+        let s0 = sut.status();
+        let s1 = sut.status(); // can call status many times!
+        assert_eq!(s0, s1);
 
         let shield0 = sut.clone().build().unwrap();
         let shield = sut.clone().build().unwrap(); // can call build many times!
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_invalid_reason.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs
similarity index 95%
rename from crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_invalid_reason.rs
rename to crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs
index 56eb64369..6fddd6ad2 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_invalid_reason.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_rule_violation.rs
@@ -1,5 +1,5 @@
 use crate::prelude::*;
-use sargon::SecurityShieldBuilderInvalidReason as InternalSecurityShieldBuilderInvalidReason;
+use sargon::SecurityShieldBuilderRuleViolation as InternalSecurityShieldBuilderRuleViolation;
 
 use thiserror::Error as ThisError;
 
@@ -7,7 +7,7 @@ use thiserror::Error as ThisError;
 #[derive(
     Clone, Debug, ThisError, PartialEq, InternalConversion, uniffi::Error,
 )]
-pub enum SecurityShieldBuilderInvalidReason {
+pub enum SecurityShieldBuilderRuleViolation {
     #[error("Auth Signing Factor Missing")]
     MissingAuthSigningFactor,
 
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_status.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_status.rs
new file mode 100644
index 000000000..380661f94
--- /dev/null
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/security_shield_builder_status.rs
@@ -0,0 +1,41 @@
+use crate::prelude::*;
+use sargon::SecurityShieldBuilderStatus as InternalSecurityShieldBuilderStatus;
+use sargon::SecurityShieldBuilderStatusInvalidReason as InternalSecurityShieldBuilderStatusInvalidReason;
+
+/// Represents the status of `SecurityShieldBuilder`.
+/// Used for UI representation in host applications.
+#[derive(Clone, Debug, PartialEq, InternalConversion, uniffi::Enum)]
+pub enum SecurityShieldBuilderStatus {
+    /// The selected factor sources form a strong combination
+    /// in the Security Shield building process.
+    Strong,
+
+    /// The selected factor sources form a weak combination
+    /// in the Security Shield building process.
+    Weak {
+        /// The reason why the built shield would be weak.
+        reason: SecurityShieldBuilderRuleViolation,
+    },
+
+    /// The selected factor sources form an invalid combination
+    /// in the Security Shield building process.
+    /// Example: Each role must have at least one factor.
+    Invalid {
+        reason: SecurityShieldBuilderStatusInvalidReason,
+    },
+}
+
+/// Represents the reason why the `SecurityShieldBuilder` has an invalid status.
+/// This struct contains the specific reasons for each component of the security shield builder
+/// being invalid. The components include:
+/// - Primary role
+/// - Recovery role
+/// - Confirmation role
+/// - Authentication signing
+#[derive(Clone, Debug, PartialEq, InternalConversion, uniffi::Record)]
+pub struct SecurityShieldBuilderStatusInvalidReason {
+    pub is_primary_role_factor_list_empty: bool,
+    pub is_recovery_role_factor_list_empty: bool,
+    pub is_confirmation_role_factor_list_empty: bool,
+    pub is_auth_signing_factor_missing: bool,
+}
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/selected_primary_threshold_factors_status.rs b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/selected_primary_threshold_factors_status.rs
index 20cf7fe0d..a51214ac7 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/selected_primary_threshold_factors_status.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/profile/mfa/security_structures/selected_primary_threshold_factors_status.rs
@@ -38,6 +38,6 @@ pub enum SelectedPrimaryThresholdFactorsStatusInvalidReason {
         factor_source_kind: FactorSourceKind,
     },
     Other {
-        underlying: SecurityShieldBuilderInvalidReason,
+        underlying: SecurityShieldBuilderRuleViolation,
     },
 }
diff --git a/crates/uniffi/uniffi_SPLIT_ME/src/system/sargon_os/sargon_os_security_structures.rs b/crates/uniffi/uniffi_SPLIT_ME/src/system/sargon_os/sargon_os_security_structures.rs
index 0a691663a..a8c375820 100644
--- a/crates/uniffi/uniffi_SPLIT_ME/src/system/sargon_os/sargon_os_security_structures.rs
+++ b/crates/uniffi/uniffi_SPLIT_ME/src/system/sargon_os/sargon_os_security_structures.rs
@@ -52,7 +52,7 @@ impl SargonOS {
     pub async fn add_security_structure_of_factor_source_ids(
         &self,
         structure_ids: &SecurityStructureOfFactorSourceIDs,
-    ) -> Result<bool> {
+    ) -> Result<()> {
         self.wrapped
             .add_security_structure_of_factor_source_ids(
                 &structure_ids.into_internal(),
diff --git a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SharedConstants.kt b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SharedConstants.kt
index 6aeaccd2b..213122ffc 100644
--- a/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SharedConstants.kt
+++ b/jvm/sargon-android/src/main/java/com/radixdlt/sargon/extensions/SharedConstants.kt
@@ -25,5 +25,6 @@ val Account.Companion.nameMaxLength: Long
 val Persona.Companion.nameMaxLength: Long
     get() = entityNameMaxLength
 
+@KoverIgnore
 val DisplayName.Companion.maxLength: Long
     get() = displayNameMaxLength
\ No newline at end of file