input) {
+    if (input == null) {
+      return new java.util.ArrayList<>();
+    }
+    return input.stream()
+            .filter(s -> s != null && !s.trim().isEmpty())
+            .collect(java.util.stream.Collectors.toList());
+  }
+
+  /**
+   * Custom builder for Statement to handle conditions.
+   */
+  public static class StatementBuilder {
+    /**
+     * Adds a condition to the statement.
+     *
+     * @param operator the condition operator
+     * @param key the condition key
+     * @param value the condition value
+     * @return this builder
+     */
+    public StatementBuilder condition(String operator, String key, Object value) {
+      if (operator != null && key != null && value != null) {
+        if (this.conditions == null) {
+          this.conditions = new java.util.HashMap<>();
+        }
+        this.conditions.computeIfAbsent(operator, k -> new java.util.HashMap<>())
+                .put(key, value);
+      }
+      return this;
+    }
+  }
+
+
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    Statement statement = (Statement) o;
+    return Objects.equals(sid, statement.sid)
+        && Objects.equals(effect, statement.effect)
+        && Objects.equals(principals, statement.principals)
+        && Objects.equals(actions, statement.actions)
+        && Objects.equals(resources, statement.resources)
+        && Objects.equals(conditions, statement.conditions);
+  }
+
+  @Override
+  public int hashCode() {
+    return Objects.hash(sid, effect, principals, actions, resources, conditions);
+  }
+
+  @Override
+  public String toString() {
+    return "Statement{"
+        + "sid='" + sid + '\''
+        + ", effect='" + effect + '\''
+        + ", principals=" + principals
+        + ", actions=" + actions
+        + ", resources=" + resources
+        + ", conditions=" + conditions
+        + '}';
+  }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/TrustConfiguration.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/TrustConfiguration.java
new file mode 100644
index 00000000..e059a2ab
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/TrustConfiguration.java
@@ -0,0 +1,126 @@
+package com.salesforce.multicloudj.iam.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import lombok.Getter;
+
+/**
+ * Configuration for trust relationships in identity creation.
+ *
+ * This class defines which principals can assume or impersonate the identity being created,
+ * along with any conditions that must be met for the trust relationship to be valid.
+ *
+ * 
Principal identifiers are accepted in their native cloud format and translated internally:
+ * - AWS: ARN format (arn:aws:iam::account:type/name)
+ * - GCP: Email format (serviceaccount@project.iam.gserviceaccount.com)
+ * - AliCloud: ACS format (acs:ram::account:type/name) or account ID
+ */
+@Getter
+public class TrustConfiguration {
+    private final List trustedPrincipals;
+    private final Map> conditions;
+
+    private TrustConfiguration(Builder builder) {
+        this.trustedPrincipals = new ArrayList<>(builder.trustedPrincipals);
+        this.conditions = new HashMap<>(builder.conditions);
+    }
+
+    /**
+     * Creates a new builder for TrustConfiguration.
+     *
+     * @return a new Builder instance
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        TrustConfiguration that = (TrustConfiguration) o;
+        return Objects.equals(trustedPrincipals, that.trustedPrincipals) &&
+               Objects.equals(conditions, that.conditions);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(trustedPrincipals, conditions);
+    }
+
+    @Override
+    public String toString() {
+        return "TrustConfiguration{" +
+                "trustedPrincipals=" + trustedPrincipals +
+                ", conditions=" + conditions +
+                '}';
+    }
+
+    /**
+     * Builder class for TrustConfiguration.
+     */
+    public static class Builder {
+        private final List trustedPrincipals = new ArrayList<>();
+        private final Map> conditions = new HashMap<>();
+
+        private Builder() {
+        }
+
+        /**
+         * Adds a trusted principal to the trust configuration.
+         *
+         * @param principal the principal identifier in cloud-native format (AWS ARN, GCP email, AliCloud ACS ARN or account ID)
+         * @return this Builder instance
+         */
+        public Builder addTrustedPrincipal(String principal) {
+            if (principal != null && !principal.trim().isEmpty()) {
+                this.trustedPrincipals.add(principal);
+            }
+            return this;
+        }
+
+        /**
+         * Adds multiple trusted principals to the trust configuration.
+         *
+         * @param principals the list of principal identifiers in cloud-native formats
+         * @return this Builder instance
+         */
+        public Builder addTrustedPrincipals(List principals) {
+            if (principals != null) {
+                principals.stream()
+                    .filter(p -> p != null && !p.trim().isEmpty())
+                    .forEach(this.trustedPrincipals::add);
+            }
+            return this;
+        }
+
+        /**
+         * Adds a condition to the trust configuration.
+         *
+         * @param operator the condition operator (e.g., "StringEquals", "IpAddress", "DateGreaterThan")
+         * @param key the condition key in cloud-native format (e.g., "aws:RequestedRegion", ""aws:SourceIp")
+         * @param value the condition value
+         * @return this Builder instance
+         */
+        public Builder addCondition(String operator, String key, Object value) {
+            if (operator != null && key != null && value != null) {
+                conditions.computeIfAbsent(operator, k -> new HashMap<>()).put(key, value);
+            }
+            return this;
+        }
+
+        /**
+         * Builds and returns a TrustConfiguration instance.
+         *
+         * @return a new TrustConfiguration instance
+         */
+        public TrustConfiguration build() {
+            return new TrustConfiguration(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java
new file mode 100644
index 00000000..4bb1283e
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java
@@ -0,0 +1,65 @@
+package com.salesforce.multicloudj.iam.client;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+/**
+ * Unit tests for IamClient builder pattern and basic functionality.
+ */
+public class IamClientTest {
+
+    @Test
+    public void testIamClientBuilder() {
+        // Test builder creation with different provider IDs
+        IamClient.IamClientBuilder builder = IamClient.builder("aws");
+        assertNotNull(builder);
+
+        // Test method chaining
+        IamClient.IamClientBuilder result = builder
+            .withRegion("us-west-2")
+            .withEndpoint(URI.create("https://iam.amazonaws.com"));
+
+        assertSame(builder, result, "Builder methods should return the same instance for chaining");
+    }
+
+    @Test
+    public void testIamClientBuilderWithDifferentProviders() {
+        // Test with AWS
+        IamClient.IamClientBuilder awsBuilder = IamClient.builder("aws");
+        assertNotNull(awsBuilder);
+
+        // Test with GCP
+        IamClient.IamClientBuilder gcpBuilder = IamClient.builder("gcp");
+        assertNotNull(gcpBuilder);
+
+        // Test with AliCloud
+        IamClient.IamClientBuilder aliBuilder = IamClient.builder("ali");
+        assertNotNull(aliBuilder);
+    }
+
+    @Test
+    public void testIamClientBuild() {
+        IamClient client = IamClient.builder("aws")
+            .withRegion("us-east-1")
+            .build();
+
+        assertNotNull(client);
+    }
+
+    @Test
+    public void testIamClientBuildWithEndpoint() {
+        URI customEndpoint = URI.create("https://custom-iam-endpoint.com");
+
+        IamClient client = IamClient.builder("gcp")
+            .withRegion("us-central1")
+            .withEndpoint(customEndpoint)
+            .build();
+
+        assertNotNull(client);
+    }
+
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/CreateOptionsTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/CreateOptionsTest.java
new file mode 100644
index 00000000..9feb46b7
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/CreateOptionsTest.java
@@ -0,0 +1,258 @@
+package com.salesforce.multicloudj.iam.model;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for CreateOptions builder pattern and functionality.
+ */
+public class CreateOptionsTest {
+
+    @Test
+    public void testCreateOptionsBuilder() {
+        CreateOptions options = CreateOptions.builder()
+            .path("/service-roles/")
+            .maxSessionDuration(3600)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/PowerUserBoundary")
+            .build();
+
+        assertEquals("/service-roles/", options.getPath());
+        assertEquals(Integer.valueOf(3600), options.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/PowerUserBoundary", options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderMinimal() {
+        CreateOptions options = CreateOptions.builder()
+            .build();
+
+        assertNull(options.getPath());
+        assertNull(options.getMaxSessionDuration());
+        assertNull(options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderIndividualFields() {
+        // Test path only
+        CreateOptions pathOptions = CreateOptions.builder()
+            .path("/application/backend/")
+            .build();
+
+        assertEquals("/application/backend/", pathOptions.getPath());
+        assertNull(pathOptions.getMaxSessionDuration());
+        assertNull(pathOptions.getPermissionBoundary());
+
+        // Test maxSessionDuration only
+        CreateOptions durationOptions = CreateOptions.builder()
+            .maxSessionDuration(7200)
+            .build();
+
+        assertNull(durationOptions.getPath());
+        assertEquals(Integer.valueOf(7200), durationOptions.getMaxSessionDuration());
+        assertNull(durationOptions.getPermissionBoundary());
+
+        // Test permissionBoundary only (AWS example)
+        CreateOptions boundaryOptions = CreateOptions.builder()
+            .permissionBoundary("arn:aws:iam::123456789012:policy/DeveloperBoundary")
+            .build();
+
+        assertNull(boundaryOptions.getPath());
+        assertNull(boundaryOptions.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/DeveloperBoundary", boundaryOptions.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderWithCustomSessionDurations() {
+        // Test minimum duration (900 seconds = 15 minutes)
+        CreateOptions minOptions = CreateOptions.builder()
+            .maxSessionDuration(900)
+            .build();
+        assertEquals(Integer.valueOf(900), minOptions.getMaxSessionDuration());
+
+        // Test maximum duration (43200 seconds = 12 hours)
+        CreateOptions maxOptions = CreateOptions.builder()
+            .maxSessionDuration(43200)
+            .build();
+        assertEquals(Integer.valueOf(43200), maxOptions.getMaxSessionDuration());
+
+        // Test common duration (7200 seconds = 2 hours)
+        CreateOptions commonOptions = CreateOptions.builder()
+            .maxSessionDuration(7200)
+            .build();
+        assertEquals(Integer.valueOf(7200), commonOptions.getMaxSessionDuration());
+    }
+
+
+    @Test
+    public void testCreateOptionsBuilderComplexScenario() {
+        CreateOptions options = CreateOptions.builder()
+            .path("/microservices/user-service/")
+            .maxSessionDuration(14400)  // 4 hours
+            .permissionBoundary("arn:aws:iam::123456789012:policy/MicroserviceBoundary")
+            .build();
+
+        assertEquals("/microservices/user-service/", options.getPath());
+        assertEquals(Integer.valueOf(14400), options.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/MicroserviceBoundary", options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsEqualsAndHashCode() {
+        CreateOptions options1 = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(3600)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        CreateOptions options2 = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(3600)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        CreateOptions differentPath = CreateOptions.builder()
+            .path("/different/")
+            .maxSessionDuration(3600)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        CreateOptions differentDuration = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(7200)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        CreateOptions nullOptions = CreateOptions.builder().build();
+        CreateOptions anotherNullOptions = CreateOptions.builder().build();
+
+        // Test equals
+        assertEquals(options1, options2);
+        assertEquals(options1, options1); // same object
+        assertNotEquals(options1, differentPath);
+        assertNotEquals(options1, differentDuration);
+        assertNotEquals(options1, null);
+        assertNotEquals(options1, "not create options");
+        assertEquals(nullOptions, anotherNullOptions);
+
+        // Test hashCode
+        assertEquals(options1.hashCode(), options2.hashCode());
+        assertNotEquals(options1.hashCode(), differentPath.hashCode());
+        assertEquals(nullOptions.hashCode(), anotherNullOptions.hashCode());
+    }
+
+    @Test
+    public void testCreateOptionsToString() {
+        // Test with all fields populated
+        CreateOptions options = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(7200)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        String result = options.toString();
+        assertTrue(result.contains("path='/test/'"));
+        assertTrue(result.contains("maxSessionDuration=7200"));
+        assertTrue(result.contains("permissionBoundary='arn:aws:iam::123456789012:policy/TestBoundary'"));
+
+        // Test with null values
+        CreateOptions nullOptions = CreateOptions.builder().build();
+        String nullResult = nullOptions.toString();
+        assertTrue(nullResult.contains("CreateOptions"));
+        assertTrue(nullResult.contains("path='null'"));
+        assertTrue(nullResult.contains("maxSessionDuration=null"));
+        assertTrue(nullResult.contains("permissionBoundary='null'"));
+
+        // Test with partial values
+        CreateOptions partialOptions = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(null)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        String partialResult = partialOptions.toString();
+        assertTrue(partialResult.contains("path='/test/'"));
+        assertTrue(partialResult.contains("maxSessionDuration=null"));
+        assertTrue(partialResult.contains("permissionBoundary='arn:aws:iam::123456789012:policy/TestBoundary'"));
+    }
+
+    @Test
+    public void testCreateOptionsBuilderMethodChaining() {
+        CreateOptions.CreateOptionsBuilder builder = CreateOptions.builder();
+
+        // Test that each method returns the same builder instance
+        assertSame(builder, builder.path("/test/"));
+        assertSame(builder, builder.maxSessionDuration(3600));
+        assertSame(builder, builder.permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary"));
+    }
+
+    @Test
+    public void testCreateOptionsBuilderNullValues() {
+        CreateOptions options = CreateOptions.builder()
+            .path(null)
+            .maxSessionDuration(null)
+            .permissionBoundary(null)
+            .build();
+
+        assertNull(options.getPath());
+        assertNull(options.getMaxSessionDuration());
+        assertNull(options.getPermissionBoundary());
+    }
+
+
+    @Test
+    public void testCreateOptionsBuilderOverwriteValues() {
+        CreateOptions options = CreateOptions.builder()
+            .path("/first/")
+            .path("/second/") // This should overwrite the first value
+            .maxSessionDuration(3600)
+            .maxSessionDuration(7200) // This should overwrite the first value
+            .permissionBoundary("arn:aws:iam::123456789012:policy/FirstBoundary")
+            .permissionBoundary("arn:aws:iam::123456789012:policy/SecondBoundary") // This should overwrite
+            .build();
+
+        assertEquals("/second/", options.getPath());
+        assertEquals(Integer.valueOf(7200), options.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/SecondBoundary", options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderProviderSpecificExamples() {
+        // AWS Example
+        CreateOptions awsOptions = CreateOptions.builder()
+            .path("/foo/")
+            .maxSessionDuration(43200) // 12 hours
+            .permissionBoundary("arn:aws:iam::123456789012:policy/PowerUserBoundary")
+            .build();
+
+        assertEquals("/foo/", awsOptions.getPath());
+        assertEquals(Integer.valueOf(43200), awsOptions.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/PowerUserBoundary", awsOptions.getPermissionBoundary());
+
+        // GCP Example
+        CreateOptions gcpOptions = CreateOptions.builder()
+            .path("/foo/")
+            .maxSessionDuration(3600) // 1 hour
+            .permissionBoundary("constraints/compute.restrictLoadBalancerCreationForTypes")
+            .build();
+
+        assertEquals("/foo/", gcpOptions.getPath());
+        assertEquals(Integer.valueOf(3600), gcpOptions.getMaxSessionDuration());
+        assertEquals("constraints/compute.restrictLoadBalancerCreationForTypes", gcpOptions.getPermissionBoundary());
+
+        // AliCloud Example (using Control Policy)
+        CreateOptions aliOptions = CreateOptions.builder()
+            .path("/foo/")
+            .maxSessionDuration(7200) // 2 hours
+            .permissionBoundary("cp-bp1example") // Control Policy ID
+            .build();
+
+        assertEquals("/foo/", aliOptions.getPath());
+        assertEquals(Integer.valueOf(7200), aliOptions.getMaxSessionDuration());
+        assertEquals("cp-bp1example", aliOptions.getPermissionBoundary()); // AliCloud Control Policy
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java
new file mode 100644
index 00000000..5fece1c8
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java
@@ -0,0 +1,374 @@
+package com.salesforce.multicloudj.iam.model;
+
+import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for PolicyDocument builder pattern.
+ */
+public class PolicyDocumentTest {
+
+    private static final String TEST_VERSION = "TEST_VERSION";
+
+    @Test
+    public void testPolicyDocumentBuilder() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .sid("StorageAccess")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .action("storage:PutObject")
+                .principal("arn:aws:iam::123456789012:user/ExampleUser")
+                .resource("storage://my-bucket/*")
+                .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+                .build())
+            .build();
+
+        assertEquals("2024-01-01", policy.getVersion());
+        assertEquals(1, policy.getStatements().size());
+
+        Statement statement = policy.getStatements().get(0);
+        assertEquals("StorageAccess", statement.getSid());
+        assertEquals("Allow", statement.getEffect());
+        assertEquals(Arrays.asList("storage:GetObject", "storage:PutObject"), statement.getActions());
+        assertEquals(Arrays.asList("arn:aws:iam::123456789012:user/ExampleUser"), statement.getPrincipals());
+        assertEquals(Arrays.asList("storage://my-bucket/*"), statement.getResources());
+
+        assertTrue(statement.getConditions().containsKey("StringEquals"));
+        assertEquals("us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion"));
+    }
+
+    @Test
+    public void testMultipleStatements() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(Statement.builder()
+                .sid("ReadAccess")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://my-bucket/*")
+                .build())
+            .statement(Statement.builder()
+                .sid("WriteAccess")
+                .effect("Allow")
+                .action("storage:PutObject")
+                .resource("storage://my-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(2, policy.getStatements().size());
+        assertEquals("ReadAccess", policy.getStatements().get(0).getSid());
+        assertEquals("WriteAccess", policy.getStatements().get(1).getSid());
+    }
+
+    @Test
+    public void testAddCompleteStatement() {
+        Statement statement = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://my-bucket/*")
+            .build();
+
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(statement)
+            .build();
+
+        assertEquals(1, policy.getStatements().size());
+        assertEquals("TestStatement", policy.getStatements().get(0).getSid());
+    }
+
+    @Test
+    public void testEmptyPolicyThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            PolicyDocument.builder().build();
+        });
+    }
+
+    @Test
+    public void testMissingVersionThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            PolicyDocument.builder()
+                .statement(Statement.builder()
+                    .sid("TestStatement")
+                    .effect("Allow")
+                    .action("storage:GetObject")
+                    .resource("storage://test-bucket/*")
+                    .build())
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutEffectThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            PolicyDocument.builder()
+                .version(TEST_VERSION)
+                .statement(Statement.builder()
+                    .sid("TestStatement")
+                    .action("storage:GetObject")
+                    .build())
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutActionsThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            PolicyDocument.builder()
+                .version(TEST_VERSION)
+                .statement(Statement.builder()
+                    .sid("TestStatement")
+                    .effect("Allow")
+                    .build())
+                .build();
+        });
+    }
+
+    @Test
+    public void testVersionHandling() {
+        // Test custom version
+        PolicyDocument customVersionPolicy = PolicyDocument.builder()
+            .version("2023-06-01")
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        assertEquals("2023-06-01", customVersionPolicy.getVersion());
+
+        // Test default version
+        PolicyDocument defaultVersionPolicy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(TEST_VERSION, defaultVersionPolicy.getVersion());
+    }
+
+    @Test
+    public void testBuilderMethodsWithMultipleValues() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .action("storage:PutObject")
+                .action("storage:DeleteObject")
+                .action("storage:ListObjects")
+                .resource("storage://bucket1/*")
+                .resource("storage://bucket2/*")
+                .resource("storage://bucket3/*")
+                .resource("storage://bucket4/*")
+                .principal("principal1")
+                .principal("principal2")
+                .principal("principal3")
+                .principal("principal4")
+                .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+                .condition("DateGreaterThan", "aws:CurrentTime", "2024-01-01T00:00:00Z")
+                .build())
+            .build();
+
+        Statement statement = policy.getStatements().get(0);
+
+        // Test actions
+        assertEquals(4, statement.getActions().size());
+        assertTrue(statement.getActions().contains("storage:GetObject"));
+        assertTrue(statement.getActions().contains("storage:PutObject"));
+        assertTrue(statement.getActions().contains("storage:DeleteObject"));
+        assertTrue(statement.getActions().contains("storage:ListObjects"));
+
+        // Test resources
+        assertEquals(4, statement.getResources().size());
+        assertTrue(statement.getResources().contains("storage://bucket1/*"));
+        assertTrue(statement.getResources().contains("storage://bucket2/*"));
+        assertTrue(statement.getResources().contains("storage://bucket3/*"));
+        assertTrue(statement.getResources().contains("storage://bucket4/*"));
+
+        // Test principals
+        assertEquals(4, statement.getPrincipals().size());
+        assertTrue(statement.getPrincipals().contains("principal1"));
+        assertTrue(statement.getPrincipals().contains("principal2"));
+        assertTrue(statement.getPrincipals().contains("principal3"));
+        assertTrue(statement.getPrincipals().contains("principal4"));
+
+        // Test conditions
+        assertTrue(statement.getConditions().containsKey("StringEquals"));
+        assertTrue(statement.getConditions().containsKey("DateGreaterThan"));
+    }
+
+    @Test
+    public void testBuilderAutoInitialization() {
+        // Test simple statement creation with Lombok builder
+        PolicyDocument policy1 = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(1, policy1.getStatements().size());
+        assertEquals("Allow", policy1.getStatements().get(0).getEffect());
+
+        PolicyDocument policy2 = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .effect("Allow")
+                .principal("principal1")
+                .principal("principal2")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .condition("StringEquals", "key", "value")
+                .build())
+            .build();
+
+        assertEquals(1, policy2.getStatements().size());
+        Statement statement = policy2.getStatements().get(0);
+        assertEquals("Allow", statement.getEffect());
+        assertEquals(1, statement.getActions().size());
+        assertEquals(1, statement.getResources().size());
+        assertEquals(2, statement.getPrincipals().size());
+    }
+
+    @Test
+    public void testAddNullStatement() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement((Statement) null)
+            .statement(Statement.builder()
+                .sid("ValidStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(1, policy.getStatements().size()); // Null statements are filtered out
+        assertEquals("ValidStatement", policy.getStatements().get(0).getSid());
+    }
+
+    @Test
+    public void testMixingAddStatementAndBuilder() {
+        Statement preBuiltStatement = Statement.builder()
+            .sid("PreBuilt")
+            .effect("Deny")
+            .action("storage:DeleteObject")
+            .resource("storage://sensitive-bucket/*")
+            .build();
+
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(preBuiltStatement)
+            .statement(Statement.builder()
+                .sid("BuiltInline")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://public-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(2, policy.getStatements().size());
+        assertEquals("PreBuilt", policy.getStatements().get(0).getSid());
+        assertEquals("BuiltInline", policy.getStatements().get(1).getSid());
+    }
+
+    @Test
+    public void testPolicyDocumentEqualsAndHashCode() {
+        PolicyDocument policy1 = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        PolicyDocument policy2 = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        PolicyDocument policy3 = PolicyDocument.builder()
+            .version("2023-01-01")
+            .statement(Statement.builder()
+                .sid("DifferentStatement")
+                .effect("Deny")
+                .action("storage:DeleteObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        // Test equals
+        assertEquals(policy1, policy2);
+        assertNotEquals(policy1, policy3);
+        assertNotEquals(policy1, null);
+        assertNotEquals(policy1, "not a policy");
+        assertEquals(policy1, policy1); // same object
+
+        // Test hashCode
+        assertEquals(policy1.hashCode(), policy2.hashCode());
+        assertNotEquals(policy1.hashCode(), policy3.hashCode());
+    }
+
+    @Test
+    public void testPolicyDocumentToString() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        String result = policy.toString();
+        assertTrue(result.contains("2024-01-01"));
+        assertTrue(result.contains("TestStatement"));
+        assertTrue(result.contains("PolicyDocument"));
+    }
+
+
+    @Test
+    public void testEndStatementWithoutCurrentStatement() {
+        // Simple test with Lombok builder
+        PolicyDocument policy = PolicyDocument.builder()
+            .version(TEST_VERSION)
+            .statement(Statement.builder()
+                .sid("TestStatement")
+                .effect("Allow")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build())
+            .build();
+
+        assertEquals(1, policy.getStatements().size());
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java
new file mode 100644
index 00000000..e31f95c4
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java
@@ -0,0 +1,306 @@
+package com.salesforce.multicloudj.iam.model;
+
+import com.salesforce.multicloudj.common.exceptions.InvalidArgumentException;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for Statement builder pattern and functionality.
+ */
+public class StatementTest {
+
+    @Test
+    public void testStatementBuilder() {
+        Statement statement = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .action("storage:PutObject")
+            .resource("storage://my-bucket/*")
+            .principal("arn:aws:iam::123456789012:user/TestUser")
+            .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        assertEquals("TestStatement", statement.getSid());
+        assertEquals("Allow", statement.getEffect());
+        assertEquals(Arrays.asList("storage:GetObject", "storage:PutObject"), statement.getActions());
+        assertEquals(Arrays.asList("storage://my-bucket/*"), statement.getResources());
+        assertEquals(Arrays.asList("arn:aws:iam::123456789012:user/TestUser"), statement.getPrincipals());
+
+        assertTrue(statement.getConditions().containsKey("StringEquals"));
+        assertEquals("us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion"));
+    }
+
+    @Test
+    public void testStatementBuilderMinimal() {
+        Statement statement = Statement.builder()
+            .sid("MinimalStatement")
+            .effect("Deny")
+            .action("storage:DeleteObject")
+            .resource("storage://sensitive-bucket/*")
+            .build();
+
+        assertEquals("MinimalStatement", statement.getSid());
+        assertEquals("Deny", statement.getEffect());
+        assertEquals(Arrays.asList("storage:DeleteObject"), statement.getActions());
+        assertEquals(Arrays.asList("storage://sensitive-bucket/*"), statement.getResources());
+        assertTrue(statement.getPrincipals().isEmpty());
+        assertTrue(statement.getConditions().isEmpty());
+    }
+
+    @Test
+    public void testStatementBuilderMultipleResources() {
+        List expectedResources = Arrays.asList("storage://bucket1/*", "storage://bucket2/*");
+
+        Statement statement = Statement.builder()
+            .sid("MultiResourceStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://bucket1/*")
+            .resource("storage://bucket2/*")
+            .build();
+
+        assertEquals(expectedResources, statement.getResources());
+    }
+
+    @Test
+    public void testStatementBuilderMultiplePrincipals() {
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::123456789012:user/User1",
+            "arn:aws:iam::123456789012:user/User2"
+        );
+
+        Statement statement = Statement.builder()
+            .sid("MultiPrincipalStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://shared-bucket/*")
+            .principal("arn:aws:iam::123456789012:user/User1")
+            .principal("arn:aws:iam::123456789012:user/User2")
+            .build();
+
+        assertEquals(expectedPrincipals, statement.getPrincipals());
+    }
+
+    @Test
+    public void testStatementBuilderMultipleConditions() {
+        Statement statement = Statement.builder()
+            .sid("MultiConditionStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://conditional-bucket/*")
+            .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .condition("DateGreaterThan", "aws:CurrentTime", "2024-01-01T00:00:00Z")
+            .build();
+
+        assertTrue(statement.getConditions().containsKey("StringEquals"));
+        assertTrue(statement.getConditions().containsKey("DateGreaterThan"));
+        assertEquals("us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion"));
+        assertEquals("2024-01-01T00:00:00Z", statement.getConditions().get("DateGreaterThan").get("aws:CurrentTime"));
+    }
+
+    @Test
+    public void testStatementWithoutSid() {
+        Statement statement = Statement.builder()
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://no-sid-bucket/*")
+            .build();
+
+        assertNull(statement.getSid());
+        assertEquals("Allow", statement.getEffect());
+    }
+
+    @Test
+    public void testEmptyStatementThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            Statement.builder().build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutEffectThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            Statement.builder()
+                .sid("NoEffectStatement")
+                .action("storage:GetObject")
+                .resource("storage://test-bucket/*")
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutActionsThrowsException() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            Statement.builder()
+                .sid("NoActionsStatement")
+                .effect("Allow")
+                .resource("storage://test-bucket/*")
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithEmptyEffect() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            Statement.builder()
+                .sid("EmptyEffectStatement")
+                .effect("")
+                .action("storage:GetObject")
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithWhitespaceEffect() {
+        assertThrows(InvalidArgumentException.class, () -> {
+            Statement.builder()
+                .sid("WhitespaceEffectStatement")
+                .effect("   ")
+                .action("storage:GetObject")
+                .build();
+        });
+    }
+
+    @Test
+    public void testNullAndEmptyValueHandling() {
+        Statement statement = Statement.builder()
+            .effect("Allow")
+            .action(null)
+            .action("")
+            .action("   ")
+            .action("storage:GetObject")
+            .resource(null)
+            .resource("")
+            .resource("   ")
+            .resource("storage://test-bucket/*")
+            .principal(null)
+            .principal("")
+            .principal("   ")
+            .principal("valid-principal")
+            .condition(null, "key", "value")
+            .condition("StringEquals", null, "value")
+            .condition("StringEquals", "key", null)
+            .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        assertEquals(1, statement.getActions().size());
+        assertEquals("storage:GetObject", statement.getActions().get(0));
+
+        assertEquals(1, statement.getResources().size());
+        assertEquals("storage://test-bucket/*", statement.getResources().get(0));
+
+        assertEquals(1, statement.getPrincipals().size());
+        assertEquals("valid-principal", statement.getPrincipals().get(0));
+
+        assertEquals(1, statement.getConditions().size());
+        assertTrue(statement.getConditions().containsKey("StringEquals"));
+        assertEquals("us-west-2", statement.getConditions().get("StringEquals").get("aws:RequestedRegion"));
+    }
+
+    @Test
+    public void testListMethodsWithNullValues() {
+        List principals = Arrays.asList("principal1", null, "", "   ", "principal2");
+        List actions = Arrays.asList("storage:GetObject", null, "", "   ", "storage:PutObject");
+        List resources = Arrays.asList("storage://bucket1/*", null, "", "   ", "storage://bucket2/*");
+
+        Statement statement = Statement.builder()
+            .effect("Allow")
+            .actions(actions)
+            .resources(resources)
+            .principals(principals)
+            .build();
+
+        assertEquals(2, statement.getActions().size());
+        assertTrue(statement.getActions().contains("storage:GetObject"));
+        assertTrue(statement.getActions().contains("storage:PutObject"));
+
+        assertEquals(2, statement.getResources().size());
+        assertTrue(statement.getResources().contains("storage://bucket1/*"));
+        assertTrue(statement.getResources().contains("storage://bucket2/*"));
+
+        assertEquals(2, statement.getPrincipals().size());
+        assertTrue(statement.getPrincipals().contains("principal1"));
+        assertTrue(statement.getPrincipals().contains("principal2"));
+    }
+
+    @Test
+    public void testListMethodsWithNullLists() {
+        // Test that individual actions and resources are preserved even without using list methods
+        Statement statement = Statement.builder()
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://test-bucket/*")
+            .build();
+
+        assertEquals(1, statement.getActions().size());
+        assertEquals(1, statement.getResources().size());
+        assertTrue(statement.getPrincipals().isEmpty());
+    }
+
+    @Test
+    public void testStatementEqualsAndHashCode() {
+        Statement statement1 = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://test-bucket/*")
+            .principal("principal1")
+            .build();
+
+        Statement statement2 = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://test-bucket/*")
+            .principal("principal1")
+            .build();
+
+        Statement statement3 = Statement.builder()
+            .sid("DifferentStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://test-bucket/*")
+            .build();
+
+        // Test equals
+        assertEquals(statement1, statement2);
+        assertNotEquals(statement1, statement3);
+        assertNotEquals(statement1, null);
+        assertNotEquals(statement1, "not a statement");
+        assertEquals(statement1, statement1); // same object
+
+        // Test hashCode
+        assertEquals(statement1.hashCode(), statement2.hashCode());
+        assertNotEquals(statement1.hashCode(), statement3.hashCode());
+    }
+
+    @Test
+    public void testStatementToString() {
+        Statement statement = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .action("storage:GetObject")
+            .resource("storage://test-bucket/*")
+            .principal("principal1")
+            .condition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        String result = statement.toString();
+        assertTrue(result.contains("TestStatement"));
+        assertTrue(result.contains("Allow"));
+        assertTrue(result.contains("storage:GetObject"));
+        assertTrue(result.contains("storage://test-bucket/*"));
+        assertTrue(result.contains("principal1"));
+        assertTrue(result.contains("StringEquals"));
+    }
+
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/TrustConfigurationTest.java b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/TrustConfigurationTest.java
new file mode 100644
index 00000000..afc39e1c
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/TrustConfigurationTest.java
@@ -0,0 +1,268 @@
+package com.salesforce.multicloudj.iam.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Unit tests for TrustConfiguration builder pattern and functionality.
+ */
+public class TrustConfigurationTest {
+
+    @Test
+    public void testTrustConfigurationBuilder() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addTrustedPrincipal("service-account@project.iam.gserviceaccount.com")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition("StringEquals", "aws:userid", "AIDACKCEVSQ6C2EXAMPLE")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::123456789012:root",
+            "service-account@project.iam.gserviceaccount.com"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+
+        Map> conditions = trustConfig.getConditions();
+        assertTrue(conditions.containsKey("StringEquals"));
+        assertEquals("us-west-2", conditions.get("StringEquals").get("aws:RequestedRegion"));
+        assertEquals("AIDACKCEVSQ6C2EXAMPLE", conditions.get("StringEquals").get("aws:userid"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderMinimal() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::987654321098:root")
+            .build();
+
+        assertEquals(Arrays.asList("arn:aws:iam::987654321098:root"), trustConfig.getTrustedPrincipals());
+        assertTrue(trustConfig.getConditions().isEmpty());
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderMultipleTrustedPrincipals() {
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::111111111111:root",
+            "arn:aws:iam::222222222222:root",
+            "arn:aws:iam::333333333333:user/CrossAccountUser"
+        );
+
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::111111111111:root")
+            .addTrustedPrincipal("arn:aws:iam::222222222222:root")
+            .addTrustedPrincipal("arn:aws:iam::333333333333:user/CrossAccountUser")
+            .build();
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderAddTrustedPrincipals() {
+        List principalsToAdd = Arrays.asList(
+            "arn:aws:iam::111111111111:root",
+            "arn:aws:iam::222222222222:root"
+        );
+
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addTrustedPrincipals(principalsToAdd)
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::123456789012:root",
+            "arn:aws:iam::111111111111:root",
+            "arn:aws:iam::222222222222:root"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderMultipleConditions() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition("DateGreaterThan", "aws:CurrentTime", "2024-01-01T00:00:00Z")
+            .addCondition("IpAddress", "aws:SourceIp", "203.0.113.0/24")
+            .build();
+
+        Map> conditions = trustConfig.getConditions();
+
+        assertTrue(conditions.containsKey("StringEquals"));
+        assertTrue(conditions.containsKey("DateGreaterThan"));
+        assertTrue(conditions.containsKey("IpAddress"));
+
+        assertEquals("us-west-2", conditions.get("StringEquals").get("aws:RequestedRegion"));
+        assertEquals("2024-01-01T00:00:00Z", conditions.get("DateGreaterThan").get("aws:CurrentTime"));
+        assertEquals("203.0.113.0/24", conditions.get("IpAddress").get("aws:SourceIp"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderSameOperatorMultipleConditions() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition("StringEquals", "aws:userid", "AIDACKCEVSQ6C2EXAMPLE")
+            .build();
+
+        Map> conditions = trustConfig.getConditions();
+        assertTrue(conditions.containsKey("StringEquals"));
+
+        Map stringEqualsConditions = conditions.get("StringEquals");
+        assertEquals(2, stringEqualsConditions.size());
+        assertEquals("us-west-2", stringEqualsConditions.get("aws:RequestedRegion"));
+        assertEquals("AIDACKCEVSQ6C2EXAMPLE", stringEqualsConditions.get("aws:userid"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderGcpServiceAccount() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("service-account@my-project.iam.gserviceaccount.com")
+            .addTrustedPrincipal("another-sa@different-project.iam.gserviceaccount.com")
+            .addCondition("expression", "location", "resource.name.startsWith('projects/my-project/zones/us-west')")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "service-account@my-project.iam.gserviceaccount.com",
+            "another-sa@different-project.iam.gserviceaccount.com"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+
+        Map> conditions = trustConfig.getConditions();
+        assertTrue(conditions.containsKey("expression"));
+        assertEquals("resource.name.startsWith('projects/my-project/zones/us-west')", conditions.get("expression").get("location"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderAliCloudPrincipals() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("1234567890123456")  // AliCloud account ID
+            .addTrustedPrincipal("acs:ram::1234567890123456:user/AliUser")  // AliCloud RAM user
+            .addCondition("StringEquals", "acs:CurrentRegion", "us-west-1")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "1234567890123456",
+            "acs:ram::1234567890123456:user/AliUser"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+
+        Map> conditions = trustConfig.getConditions();
+        assertTrue(conditions.containsKey("StringEquals"));
+        assertEquals("us-west-1", conditions.get("StringEquals").get("acs:CurrentRegion"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderComplexScenario() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")  // AWS account
+            .addTrustedPrincipal("service-account@project.iam.gserviceaccount.com")  // GCP service account
+            .addTrustedPrincipal("1234567890123456")  // AliCloud account
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition("StringEquals", "sts:ExternalId", "cross-cloud-external-id")
+            .addCondition("Bool", "aws:MultiFactorAuthPresent", "true")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::123456789012:root",
+            "service-account@project.iam.gserviceaccount.com",
+            "1234567890123456"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+
+        Map> conditions = trustConfig.getConditions();
+        assertTrue(conditions.containsKey("StringEquals"));
+        assertTrue(conditions.containsKey("Bool"));
+
+        assertEquals("us-west-2", conditions.get("StringEquals").get("aws:RequestedRegion"));
+        assertEquals("cross-cloud-external-id", conditions.get("StringEquals").get("sts:ExternalId"));
+        assertEquals("true", conditions.get("Bool").get("aws:MultiFactorAuthPresent"));
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderEmptyBuilder() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder().build();
+
+        assertTrue(trustConfig.getTrustedPrincipals().isEmpty());
+        assertTrue(trustConfig.getConditions().isEmpty());
+    }
+
+    @Test
+    public void testNullAndEmptyValueHandling() {
+        // Test null and empty principals
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addTrustedPrincipal(null)
+            .addTrustedPrincipal("")
+            .addTrustedPrincipal("   ")  // whitespace only
+            .addTrustedPrincipal("arn:aws:iam::987654321098:root")
+            .addTrustedPrincipals(null) // null list
+            .addTrustedPrincipals(Arrays.asList("valid-principal", null, "", "   "))
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition(null, "key", "value")  // null operator
+            .addCondition("StringEquals", null, "value")  // null key
+            .addCondition("StringEquals", "key", null)  // null value
+            .build();
+
+        // Should only have valid principals
+        assertEquals(3, trustConfig.getTrustedPrincipals().size());
+        assertTrue(trustConfig.getTrustedPrincipals().contains("arn:aws:iam::123456789012:root"));
+        assertTrue(trustConfig.getTrustedPrincipals().contains("arn:aws:iam::987654321098:root"));
+        assertTrue(trustConfig.getTrustedPrincipals().contains("valid-principal"));
+
+        // Should only have valid condition
+        assertEquals(1, trustConfig.getConditions().size());
+        assertTrue(trustConfig.getConditions().containsKey("StringEquals"));
+        assertEquals("us-west-2", trustConfig.getConditions().get("StringEquals").get("aws:RequestedRegion"));
+    }
+
+
+
+    @Test
+    public void testTrustConfigurationToString() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        String toString = trustConfig.toString();
+        assertTrue(toString.contains("trustedPrincipals"));
+        assertTrue(toString.contains("conditions"));
+        assertTrue(toString.contains("arn:aws:iam::123456789012:root"));
+    }
+
+
+    @Test
+    public void testTrustConfigurationEqualsAndHashCodeWithNullChecks() {
+        TrustConfiguration trust1 = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        TrustConfiguration trust2 = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        // Test equals with null and different types
+        assertNotEquals(trust1, null);
+        assertNotEquals(trust1, "not a trust config");
+        assertEquals(trust1, trust1); // same object
+        assertEquals(trust1, trust2); // equal objects
+
+        // Test hashCode consistency
+        assertEquals(trust1.hashCode(), trust2.hashCode());
+    }
+
+}
\ No newline at end of file
diff --git a/iam/pom.xml b/iam/pom.xml
new file mode 100644
index 00000000..9bc5d270
--- /dev/null
+++ b/iam/pom.xml
@@ -0,0 +1,19 @@
+
+
+    4.0.0
+    
+        com.salesforce.multicloudj
+        multicloudj-parent
+        ${revision}
+        ../pom.xml
+    
+    iam
+    pom
+    MultiCloudJ IAM
+    MultiCloudJ Identity and Access Management
+    
+        iam-client
+    
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 27ac0264..dcf18a41 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,6 +32,7 @@
     
 
     
+        iam
         blob
         docstore
         examples