diff --git a/iam/iam-client/pom.xml b/iam/iam-client/pom.xml
new file mode 100644
index 00000000..e371cf45
--- /dev/null
+++ b/iam/iam-client/pom.xml
@@ -0,0 +1,97 @@
+
+
+    4.0.0
+
+    iam-client
+    jar
+    MultiCloudJ - IAM Client
+
+    
+        com.salesforce.multicloudj
+        iam
+        ${revision}
+        ../pom.xml
+    
+
+    
+        
+        
+            com.salesforce.multicloudj
+            multicloudj-common
+        
+        
+            com.salesforce.multicloudj
+            sts-client
+        
+
+        
+        
+            org.junit.jupiter
+            junit-jupiter-api
+            5.12.1
+            test
+        
+        
+            org.mockito
+            mockito-core
+            5.16.1
+            test
+        
+        
+            org.mockito
+            mockito-junit-jupiter
+            5.16.1
+            test
+        
+        
+            com.salesforce.multicloudj
+            multicloudj-common
+            test-jar
+            test
+        
+    
+
+    
+        
+            
+                org.apache.maven.plugins
+                maven-jar-plugin
+                3.4.2
+                
+                    
+                        
+                            test-jar
+                        
+                    
+                
+            
+
+            
+                org.apache.maven.plugins
+                maven-surefire-plugin
+                3.4.0
+            
+            
+                org.apache.maven.plugins
+                maven-failsafe-plugin
+                3.4.0
+                
+                    
+                        run-integration-tests
+                        integration-test
+                        
+                            integration-test
+                        
+                    
+                    
+                        verify-integration-results
+                        verify
+                        
+                            verify
+                        
+                    
+                
+            
+        
+    
+
\ No newline at end of file
diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/client/IamClient.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/client/IamClient.java
new file mode 100644
index 00000000..8189e09a
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/client/IamClient.java
@@ -0,0 +1,212 @@
+package com.salesforce.multicloudj.iam.client;
+
+import com.salesforce.multicloudj.iam.model.CreateOptions;
+import com.salesforce.multicloudj.iam.model.PolicyDocument;
+import com.salesforce.multicloudj.iam.model.TrustConfiguration;
+import com.salesforce.multicloudj.sts.model.CredentialsOverrider;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Entry point for client code to interact with Identity and Access Management (IAM) services
+ * in a substrate-agnostic way.
+ *
+ * 
This client provides unified IAM operations across multiple cloud providers including
+ * AWS IAM, GCP IAM, and AliCloud RAM. It handles the complexity of different cloud IAM models
+ * and provides a consistent API for identity lifecycle management and policy operations.
+ *
+ * 
Usage example:
+ * 
+ * IamClient client = IamClient.builder("aws")
+ *     .withRegion("us-west-2")
+ *     .build();
+ *
+ * // Create identity
+ * String identityId = client.createIdentity("MyRole", "Example role", "123456789012", "us-west-2",
+ *     Optional.empty(), Optional.empty());
+ *
+ * // Create policy
+ * PolicyDocument policy = PolicyDocument.builder()
+ *     .version("2024-01-01")
+ *     .statement("StorageAccess")
+ *         .effect("Allow")
+ *         .addAction("storage:GetObject")
+ *         .addResource("storage://my-bucket/*")
+ *     .endStatement()
+ *     .build();
+ *
+ * // Attach policy
+ * client.attachInlinePolicy(policy, "123456789012", "us-west-2", "my-bucket");
+ * 
+ *
+ * @since 0.3.0
+ */
+public class IamClient {
+
+    /**
+     * Protected constructor for IamClient.
+     * Use the builder pattern to create instances.
+     */
+    protected IamClient() {
+        // Implementation will be added later when AbstractIamService is available
+    }
+
+    /**
+     * Creates a new IamClientBuilder for the specified provider.
+     *
+     * @param providerId the ID of the provider such as "aws", "gcp", or "ali"
+     * @return a new IamClientBuilder instance
+     */
+    public static IamClientBuilder builder(String providerId) {
+        return new IamClientBuilder(providerId);
+    }
+
+    /**
+     * Creates a new identity (role/service account) in the cloud provider.
+     *
+     * @param identityName the name of the identity to create
+     * @param description optional description for the identity (can be null)
+     * @param tenantId the tenant ID (AWS Account ID, GCP Project ID, or AliCloud Account ID)
+     * @param region the region for IAM operations
+     * @param trustConfig optional trust configuration
+     * @param options optional creation options
+     * @return the unique identifier of the created identity
+     */
+    public String createIdentity(String identityName, String description, String tenantId, String region,
+                                Optional trustConfig, Optional options) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Attaches an inline policy to a resource.
+     *
+     * @param policyDocument the policy document in substrate-neutral format
+     * @param tenantId the tenant ID
+     * @param region the region
+     * @param resource the resource to attach the policy to
+     */
+    public void attachInlinePolicy(PolicyDocument policyDocument, String tenantId, String region, String resource) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Retrieves the details of a specific inline policy attached to an identity.
+     *
+     * @param identityName the name of the identity
+     * @param policyName the name of the policy
+     * @param tenantId the tenant ID
+     * @param region the region
+     * @return the policy document details as a string
+     */
+    public String getInlinePolicyDetails(String identityName, String policyName, String tenantId, String region) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Lists all inline policies attached to an identity.
+     *
+     * @param identityName the name of the identity
+     * @param tenantId the tenant ID
+     * @param region the region
+     * @return a list of policy names
+     */
+    public List getAttachedPolicies(String identityName, String tenantId, String region) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Removes an inline policy from an identity.
+     *
+     * @param identityName the name of the identity
+     * @param policyName the name of the policy to remove
+     * @param tenantId the tenant ID
+     * @param region the region
+     */
+    public void removePolicy(String identityName, String policyName, String tenantId, String region) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Deletes an identity from the cloud provider.
+     *
+     * @param identityName the name of the identity to delete
+     * @param tenantId the tenant ID
+     * @param region the region
+     */
+    public void deleteIdentity(String identityName, String tenantId, String region) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Retrieves metadata about an identity.
+     *
+     * @param identityName the name of the identity
+     * @param tenantId the tenant ID
+     * @param region the region
+     * @return the unique identity identifier (ARN, email, or roleId)
+     */
+    public String getIdentity(String identityName, String tenantId, String region) {
+        // Implementation will be added when driver layer is available
+        throw new UnsupportedOperationException("Implementation will be added when driver layer is available");
+    }
+
+    /**
+     * Builder class for IamClient.
+     */
+    public static class IamClientBuilder {
+        protected String region;
+        protected URI endpoint;
+
+        /**
+         * Constructor for IamClientBuilder.
+         *
+         * @param providerId the ID of the provider such as "aws", "gcp", or "ali"
+         */
+        public IamClientBuilder(String providerId) {
+            // Implementation will be added when ServiceLoader and AbstractIamService are available
+            // Will find and initialize the provider builder here
+        }
+
+        /**
+         * Sets the region for the IAM client.
+         *
+         * @param region the region to set
+         * @return this IamClientBuilder instance
+         */
+        public IamClientBuilder withRegion(String region) {
+            this.region = region;
+            // Implementation will be added later to delegate to underlying provider builder
+            return this;
+        }
+
+        /**
+         * Sets the endpoint to override for the IAM client.
+         *
+         * @param endpoint the endpoint to set
+         * @return this IamClientBuilder instance
+         */
+        public IamClientBuilder withEndpoint(URI endpoint) {
+            this.endpoint = endpoint;
+            // Implementation will be added later to delegate to underlying provider builder
+            return this;
+        }
+
+        /**
+         * Builds and returns an IamClient instance.
+         *
+         * @return a new IamClient instance
+         */
+        public IamClient build() {
+            // Implementation will be added when ServiceLoader and AbstractIamService are available
+            return new IamClient();
+        }
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/CreateOptions.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/CreateOptions.java
new file mode 100644
index 00000000..3da2946d
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/CreateOptions.java
@@ -0,0 +1,146 @@
+package com.salesforce.multicloudj.iam.model;
+
+import java.util.Objects;
+
+/**
+ * Optional configuration for identity creation operations.
+ *
+ * This class provides additional options that can be set during identity creation,
+ * such as path specifications, session duration limits, and permission boundaries.
+ *
+ * 
Usage example:
+ * 
+ * CreateOptions options = CreateOptions.builder()
+ *     .path("/orgstore/")
+ *     .maxSessionDuration(43200) // 12 hours
+ *     .permissionBoundary("arn:aws:iam::123456789012:policy/PowerUserBoundary")
+ *     .build();
+ * 
+ *
+ * @since 0.3.0
+ */
+public class CreateOptions {
+    private final String path;
+    private final Integer maxSessionDuration;
+    private final String permissionBoundary;
+
+    private CreateOptions(Builder builder) {
+        this.path = builder.path;
+        this.maxSessionDuration = builder.maxSessionDuration;
+        this.permissionBoundary = builder.permissionBoundary;
+    }
+
+    /**
+     * Creates a new builder for CreateOptions.
+     *
+     * @return a new Builder instance
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Gets the path for the identity.
+     *
+     * @return the path, or null if not set
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * Gets the maximum session duration in seconds.
+     *
+     * @return the maximum session duration, or null if not set
+     */
+    public Integer getMaxSessionDuration() {
+        return maxSessionDuration;
+    }
+
+    /**
+     * Gets the permission boundary ARN.
+     *
+     * @return the permission boundary ARN, or null if not set
+     */
+    public String getPermissionBoundary() {
+        return permissionBoundary;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        CreateOptions that = (CreateOptions) o;
+        return Objects.equals(path, that.path) &&
+               Objects.equals(maxSessionDuration, that.maxSessionDuration) &&
+               Objects.equals(permissionBoundary, that.permissionBoundary);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(path, maxSessionDuration, permissionBoundary);
+    }
+
+    @Override
+    public String toString() {
+        return "CreateOptions{" +
+                "path='" + path + '\'' +
+                ", maxSessionDuration=" + maxSessionDuration +
+                ", permissionBoundary='" + permissionBoundary + '\'' +
+                '}';
+    }
+
+    /**
+     * Builder class for CreateOptions.
+     */
+    public static class Builder {
+        private String path;
+        private Integer maxSessionDuration;
+        private String permissionBoundary;
+
+        private Builder() {
+        }
+
+        /**
+         * Sets the path for the identity.
+         *
+         * @param path the path (e.g., "/orgstore/") for organizing identities
+         * @return this Builder instance
+         */
+        public Builder path(String path) {
+            this.path = path;
+            return this;
+        }
+
+        /**
+         * Sets the maximum session duration in seconds.
+         *
+         * @param maxSessionDuration the maximum session duration (typically up to 12 hours = 43200 seconds)
+         * @return this Builder instance
+         */
+        public Builder maxSessionDuration(Integer maxSessionDuration) {
+            this.maxSessionDuration = maxSessionDuration;
+            return this;
+        }
+
+        /**
+         * Sets the permission boundary ARN.
+         *
+         * @param permissionBoundary the ARN of the policy that acts as a permissions boundary
+         * @return this Builder instance
+         */
+        public Builder permissionBoundary(String permissionBoundary) {
+            this.permissionBoundary = permissionBoundary;
+            return this;
+        }
+
+        /**
+         * Builds and returns a CreateOptions instance.
+         *
+         * @return a new CreateOptions instance
+         */
+        public CreateOptions build() {
+            return new CreateOptions(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java
new file mode 100644
index 00000000..c6acae2e
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/PolicyDocument.java
@@ -0,0 +1,272 @@
+package com.salesforce.multicloudj.iam.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Represents a substrate-neutral policy document containing multiple statements.
+ *
+ * This class provides a cloud-agnostic way to define IAM policies that can be
+ * translated to AWS, GCP, or AliCloud native formats. The policy uses a builder
+ * pattern to prevent JSON parsing errors and provides type safety.
+ *
+ * 
Usage example:
+ * 
+ * PolicyDocument policy = PolicyDocument.builder()
+ *     .version("2024-01-01")
+ *     .statement("StorageAccess")
+ *         .effect("Allow")
+ *         .addAction("storage:GetObject")
+ *         .addAction("storage:PutObject")
+ *         .addPrincipal("arn:aws:iam::123456789012:user/ExampleUser")
+ *         .addResource("storage://my-bucket/*")
+ *         .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+ *     .endStatement()
+ *     .build();
+ * 
+ *
+ * @since 0.3.0
+ */
+public class PolicyDocument {
+    private final String version;
+    private final List statements;
+
+    private PolicyDocument(Builder builder) {
+        this.version = builder.version;
+        this.statements = new ArrayList<>(builder.statements);
+    }
+
+    /**
+     * Creates a new builder for PolicyDocument.
+     *
+     * @return a new Builder instance
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Gets the policy version.
+     *
+     * @return the policy version
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Gets the list of statements.
+     *
+     * @return an immutable copy of the statements list
+     */
+    public List getStatements() {
+        return new ArrayList<>(statements);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        PolicyDocument that = (PolicyDocument) o;
+        return Objects.equals(version, that.version) &&
+               Objects.equals(statements, that.statements);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(version, statements);
+    }
+
+    @Override
+    public String toString() {
+        return "PolicyDocument{" +
+                "version='" + version + '\'' +
+                ", statements=" + statements +
+                '}';
+    }
+
+    /**
+     * Builder class for PolicyDocument.
+     */
+    public static class Builder {
+        private String version = "2024-01-01";
+        private final List statements = new ArrayList<>();
+        private Statement.Builder currentStatementBuilder;
+
+        private Builder() {
+        }
+
+        /**
+         * Sets the policy version.
+         *
+         * @param version the policy version (default: "2024-01-01")
+         * @return this Builder instance
+         */
+        public Builder version(String version) {
+            this.version = version;
+            return this;
+        }
+
+        /**
+         * Starts building a new statement with the given SID.
+         *
+         * @param sid the statement ID
+         * @return this Builder instance configured for statement building
+         */
+        public Builder statement(String sid) {
+            finalizeCurrentStatement();
+            this.currentStatementBuilder = Statement.builder().sid(sid);
+            return this;
+        }
+
+        /**
+         * Sets the effect for the current statement.
+         *
+         * @param effect "Allow" or "Deny"
+         * @return this Builder instance
+         */
+        public Builder effect(String effect) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.effect(effect);
+            return this;
+        }
+
+        /**
+         * Adds a principal to the current statement.
+         *
+         * @param principal the principal (fully qualified principal required)
+         * @return this Builder instance
+         */
+        public Builder addPrincipal(String principal) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addPrincipal(principal);
+            return this;
+        }
+
+        /**
+         * Adds multiple principals to the current statement.
+         *
+         * @param principals the list of principals
+         * @return this Builder instance
+         */
+        public Builder addPrincipals(List principals) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addPrincipals(principals);
+            return this;
+        }
+
+        /**
+         * Adds an action to the current statement.
+         *
+         * @param action the action in substrate-neutral format
+         * @return this Builder instance
+         */
+        public Builder addAction(String action) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addAction(action);
+            return this;
+        }
+
+        /**
+         * Adds multiple actions to the current statement.
+         *
+         * @param actions the list of actions
+         * @return this Builder instance
+         */
+        public Builder addActions(List actions) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addActions(actions);
+            return this;
+        }
+
+        /**
+         * Adds a resource to the current statement.
+         *
+         * @param resource the resource in URI format
+         * @return this Builder instance
+         */
+        public Builder addResource(String resource) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addResource(resource);
+            return this;
+        }
+
+        /**
+         * Adds multiple resources to the current statement.
+         *
+         * @param resources the list of resources
+         * @return this Builder instance
+         */
+        public Builder addResources(List resources) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addResources(resources);
+            return this;
+        }
+
+        /**
+         * Adds a condition to the current statement.
+         *
+         * @param operator the condition operator
+         * @param key the condition key
+         * @param value the condition value
+         * @return this Builder instance
+         */
+        public Builder addCondition(String operator, String key, Object value) {
+            validateCurrentStatement();
+            this.currentStatementBuilder.addCondition(operator, key, value);
+            return this;
+        }
+
+        /**
+         * Ends the current statement and adds it to the policy.
+         *
+         * @return this Builder instance
+         */
+        public Builder endStatement() {
+            finalizeCurrentStatement();
+            return this;
+        }
+
+        /**
+         * Adds a complete statement to the policy document.
+         *
+         * @param statement the statement to add
+         * @return this Builder instance
+         */
+        public Builder addStatement(Statement statement) {
+            finalizeCurrentStatement();
+            if (statement != null) {
+                this.statements.add(statement);
+            }
+            return this;
+        }
+
+        /**
+         * Builds and returns a PolicyDocument instance.
+         *
+         * @return a new PolicyDocument instance
+         * @throws IllegalArgumentException if no statements are defined
+         */
+        public PolicyDocument build() {
+            finalizeCurrentStatement();
+            if (statements.isEmpty()) {
+                throw new IllegalArgumentException("at least one statement is required");
+            }
+            return new PolicyDocument(this);
+        }
+
+        private void validateCurrentStatement() {
+            if (currentStatementBuilder == null) {
+                throw new IllegalStateException("No statement is currently being built. Call statement(sid) first.");
+            }
+        }
+
+        private void finalizeCurrentStatement() {
+            if (currentStatementBuilder != null) {
+                statements.add(currentStatementBuilder.build());
+                currentStatementBuilder = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java
new file mode 100644
index 00000000..d14ea250
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/Statement.java
@@ -0,0 +1,291 @@
+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;
+
+/**
+ * Represents a single statement within a policy document.
+ *
+ * A statement defines the permissions, principals, resources, and conditions
+ * for a specific set of actions in a substrate-neutral format.
+ *
+ * 
Usage example:
+ * 
+ * Statement statement = Statement.builder()
+ *     .sid("StorageAccess")
+ *     .effect("Allow")
+ *     .addAction("storage:GetObject")
+ *     .addAction("storage:PutObject")
+ *     .addPrincipal("arn:aws:iam::123456789012:user/ExampleUser")
+ *     .addResource("storage://my-bucket/*")
+ *     .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+ *     .build();
+ * 
+ *
+ * @since 0.3.0
+ */
+public class Statement {
+    private final String sid;
+    private final String effect;
+    private final List principals;
+    private final List actions;
+    private final List resources;
+    private final Map> conditions;
+
+    private Statement(Builder builder) {
+        this.sid = builder.sid;
+        this.effect = builder.effect;
+        this.principals = new ArrayList<>(builder.principals);
+        this.actions = new ArrayList<>(builder.actions);
+        this.resources = new ArrayList<>(builder.resources);
+        this.conditions = new HashMap<>(builder.conditions);
+    }
+
+    /**
+     * Creates a new builder for Statement.
+     *
+     * @return a new Builder instance
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * Gets the statement ID.
+     *
+     * @return the statement ID, or null if not set
+     */
+    public String getSid() {
+        return sid;
+    }
+
+    /**
+     * Gets the effect (Allow or Deny).
+     *
+     * @return the effect
+     */
+    public String getEffect() {
+        return effect;
+    }
+
+    /**
+     * Gets the list of principals.
+     *
+     * @return an immutable copy of the principals list
+     */
+    public List getPrincipals() {
+        return new ArrayList<>(principals);
+    }
+
+    /**
+     * Gets the list of actions.
+     *
+     * @return an immutable copy of the actions list
+     */
+    public List getActions() {
+        return new ArrayList<>(actions);
+    }
+
+    /**
+     * Gets the list of resources.
+     *
+     * @return an immutable copy of the resources list
+     */
+    public List getResources() {
+        return new ArrayList<>(resources);
+    }
+
+    /**
+     * Gets the conditions map.
+     *
+     * @return an immutable copy of the conditions map
+     */
+    public Map> getConditions() {
+        return new HashMap<>(conditions);
+    }
+
+    @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 +
+                '}';
+    }
+
+    /**
+     * Builder class for Statement.
+     */
+    public static class Builder {
+        private String sid;
+        private String effect;
+        private final List principals = new ArrayList<>();
+        private final List actions = new ArrayList<>();
+        private final List resources = new ArrayList<>();
+        private final Map> conditions = new HashMap<>();
+
+        private Builder() {
+        }
+
+        /**
+         * Sets the statement ID.
+         *
+         * @param sid the unique identifier for this statement within the policy
+         * @return this Builder instance
+         */
+        public Builder sid(String sid) {
+            this.sid = sid;
+            return this;
+        }
+
+        /**
+         * Sets the effect.
+         *
+         * @param effect "Allow" or "Deny"
+         * @return this Builder instance
+         */
+        public Builder effect(String effect) {
+            this.effect = effect;
+            return this;
+        }
+
+        /**
+         * Adds a principal to the statement.
+         *
+         * @param principal the principal (fully qualified principal required)
+         * @return this Builder instance
+         */
+        public Builder addPrincipal(String principal) {
+            if (principal != null && !principal.trim().isEmpty()) {
+                this.principals.add(principal);
+            }
+            return this;
+        }
+
+        /**
+         * Adds multiple principals to the statement.
+         *
+         * @param principals the list of principals
+         * @return this Builder instance
+         */
+        public Builder addPrincipals(List principals) {
+            if (principals != null) {
+                principals.stream()
+                    .filter(p -> p != null && !p.trim().isEmpty())
+                    .forEach(this.principals::add);
+            }
+            return this;
+        }
+
+        /**
+         * Adds an action to the statement.
+         *
+         * @param action the action in substrate-neutral format (e.g., "storage:GetObject")
+         * @return this Builder instance
+         */
+        public Builder addAction(String action) {
+            if (action != null && !action.trim().isEmpty()) {
+                this.actions.add(action);
+            }
+            return this;
+        }
+
+        /**
+         * Adds multiple actions to the statement.
+         *
+         * @param actions the list of actions
+         * @return this Builder instance
+         */
+        public Builder addActions(List actions) {
+            if (actions != null) {
+                actions.stream()
+                    .filter(a -> a != null && !a.trim().isEmpty())
+                    .forEach(this.actions::add);
+            }
+            return this;
+        }
+
+        /**
+         * Adds a resource to the statement.
+         *
+         * @param resource the resource in URI format (e.g., "storage://my-bucket/*")
+         * @return this Builder instance
+         */
+        public Builder addResource(String resource) {
+            if (resource != null && !resource.trim().isEmpty()) {
+                this.resources.add(resource);
+            }
+            return this;
+        }
+
+        /**
+         * Adds multiple resources to the statement.
+         *
+         * @param resources the list of resources
+         * @return this Builder instance
+         */
+        public Builder addResources(List resources) {
+            if (resources != null) {
+                resources.stream()
+                    .filter(r -> r != null && !r.trim().isEmpty())
+                    .forEach(this.resources::add);
+            }
+            return this;
+        }
+
+        /**
+         * Adds a condition to the statement.
+         *
+         * @param operator the condition operator (e.g., "StringEquals", "IpAddress")
+         * @param key the condition key (e.g., "aws:RequestedRegion")
+         * @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 Statement instance.
+         *
+         * @return a new Statement instance
+         * @throws IllegalArgumentException if required fields are missing
+         */
+        public Statement build() {
+            if (effect == null || effect.trim().isEmpty()) {
+                throw new IllegalArgumentException("effect is required");
+            }
+            if (actions.isEmpty()) {
+                throw new IllegalArgumentException("at least one action is required");
+            }
+            return new Statement(this);
+        }
+    }
+}
\ 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..20f9f114
--- /dev/null
+++ b/iam/iam-client/src/main/java/com/salesforce/multicloudj/iam/model/TrustConfiguration.java
@@ -0,0 +1,146 @@
+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;
+
+/**
+ * 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.
+ *
+ * 
Usage example:
+ * 
+ * TrustConfiguration trust = TrustConfiguration.builder()
+ *     .addTrustedPrincipal("arn:aws:iam::111122223333:root")
+ *     .addTrustedPrincipal("arn:aws:iam::444455556666:user/ExampleUser")
+ *     .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+ *     .build();
+ * 
+ *
+ * @since 0.3.0
+ */
+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();
+    }
+
+    /**
+     * Gets the list of trusted principals.
+     *
+     * @return an immutable copy of the trusted principals list
+     */
+    public List getTrustedPrincipals() {
+        return new ArrayList<>(trustedPrincipals);
+    }
+
+    /**
+     * Gets the trust conditions.
+     *
+     * @return an immutable copy of the conditions map
+     */
+    public Map> getConditions() {
+        return new HashMap<>(conditions);
+    }
+
+    @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 ARN or identifier that can assume this identity
+         * @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 ARNs or identifiers
+         * @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")
+         * @param key the condition key (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..d802fea8
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/client/IamClientTest.java
@@ -0,0 +1,148 @@
+package com.salesforce.multicloudj.iam.client;
+
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * 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);
+    }
+
+    // TODO: Modify this test to verify actual createIdentity functionality
+    // Expected behavior: Should return the unique identifier of the created identity
+    @Test
+    public void testCreateIdentity() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.createIdentity("TestRole", "Test description", "123456789012", "us-west-2",
+                java.util.Optional.empty(), java.util.Optional.empty());
+        });
+    }
+
+    // TODO: Modify this test to verify actual attachInlinePolicy functionality
+    // Expected behavior: Should successfully attach policy without throwing exceptions
+    @Test
+    public void testAttachInlinePolicy() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.attachInlinePolicy(null, "123456789012", "us-west-2", "test-resource");
+        });
+    }
+
+    // TODO: Modify this test to verify actual getInlinePolicyDetails functionality
+    // Expected behavior: Should return the policy document details as a string
+    @Test
+    public void testGetInlinePolicyDetails() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.getInlinePolicyDetails("TestRole", "TestPolicy", "123456789012", "us-west-2");
+        });
+    }
+
+    // TODO: Modify this test to verify actual getAttachedPolicies functionality
+    // Expected behavior: Should return a list of policy names attached to the identity
+    @Test
+    public void testGetAttachedPolicies() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.getAttachedPolicies("TestRole", "123456789012", "us-west-2");
+        });
+    }
+
+    // TODO: Modify this test to verify actual removePolicy functionality
+    // Expected behavior: Should successfully remove policy without throwing exceptions
+    @Test
+    public void testRemovePolicy() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.removePolicy("TestRole", "TestPolicy", "123456789012", "us-west-2");
+        });
+    }
+
+    // TODO: Modify this test to verify actual deleteIdentity functionality
+    // Expected behavior: Should successfully delete identity without throwing exceptions
+    @Test
+    public void testDeleteIdentity() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.deleteIdentity("TestRole", "123456789012", "us-west-2");
+        });
+    }
+
+    // TODO: Modify this test to verify actual getIdentity functionality
+    // Expected behavior: Should return the unique identity identifier (ARN, email, or roleId)
+    @Test
+    public void testGetIdentity() {
+        IamClient client = IamClient.builder("aws").build();
+
+        // Currently throws UnsupportedOperationException, will be implemented later
+        assertThrows(UnsupportedOperationException.class, () -> {
+            client.getIdentity("TestRole", "123456789012", "us-west-2");
+        });
+    }
+}
\ 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..51d83ff3
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/CreateOptionsTest.java
@@ -0,0 +1,199 @@
+package com.salesforce.multicloudj.iam.model;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * 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 testCreateOptionsBuilderWithPath() {
+        CreateOptions options = CreateOptions.builder()
+            .path("/application/backend/")
+            .build();
+
+        assertEquals("/application/backend/", options.getPath());
+        assertNull(options.getMaxSessionDuration());
+        assertNull(options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderWithMaxSessionDuration() {
+        CreateOptions options = CreateOptions.builder()
+            .maxSessionDuration(7200)
+            .build();
+
+        assertNull(options.getPath());
+        assertEquals(Integer.valueOf(7200), options.getMaxSessionDuration());
+        assertNull(options.getPermissionBoundary());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderWithPermissionBoundary() {
+        CreateOptions options = CreateOptions.builder()
+            .permissionBoundary("arn:aws:iam::123456789012:policy/DeveloperBoundary")
+            .build();
+
+        assertNull(options.getPath());
+        assertNull(options.getMaxSessionDuration());
+        assertEquals("arn:aws:iam::123456789012:policy/DeveloperBoundary", options.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 testCreateOptionsBuilderWithDifferentPaths() {
+        // Test root path
+        CreateOptions rootOptions = CreateOptions.builder()
+            .path("/")
+            .build();
+        assertEquals("/", rootOptions.getPath());
+
+        // Test nested path
+        CreateOptions nestedOptions = CreateOptions.builder()
+            .path("/division/team/service/")
+            .build();
+        assertEquals("/division/team/service/", nestedOptions.getPath());
+
+        // Test simple path
+        CreateOptions simpleOptions = CreateOptions.builder()
+            .path("/service-roles/")
+            .build();
+        assertEquals("/service-roles/", simpleOptions.getPath());
+    }
+
+    @Test
+    public void testCreateOptionsBuilderWithDifferentPermissionBoundaries() {
+        // Test AWS IAM policy ARN
+        CreateOptions awsOptions = CreateOptions.builder()
+            .permissionBoundary("arn:aws:iam::123456789012:policy/PowerUserBoundary")
+            .build();
+        assertEquals("arn:aws:iam::123456789012:policy/PowerUserBoundary", awsOptions.getPermissionBoundary());
+
+        // Test different policy name
+        CreateOptions devOptions = CreateOptions.builder()
+            .permissionBoundary("arn:aws:iam::987654321098:policy/DeveloperBoundary")
+            .build();
+        assertEquals("arn:aws:iam::987654321098:policy/DeveloperBoundary", devOptions.getPermissionBoundary());
+    }
+
+    @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 testCreateOptionsEquality() {
+        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 options3 = CreateOptions.builder()
+            .path("/different/")
+            .maxSessionDuration(3600)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        assertEquals(options1, options2);
+        assertNotEquals(options1, options3);
+        assertEquals(options1.hashCode(), options2.hashCode());
+    }
+
+    @Test
+    public void testCreateOptionsToString() {
+        CreateOptions options = CreateOptions.builder()
+            .path("/test/")
+            .maxSessionDuration(7200)
+            .permissionBoundary("arn:aws:iam::123456789012:policy/TestBoundary")
+            .build();
+
+        String toString = options.toString();
+        assertTrue(toString.contains("path='/test/'"));
+        assertTrue(toString.contains("maxSessionDuration=7200"));
+        assertTrue(toString.contains("permissionBoundary='arn:aws:iam::123456789012:policy/TestBoundary'"));
+    }
+
+    @Test
+    public void testCreateOptionsBuilderMethodChaining() {
+        CreateOptions.Builder 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());
+    }
+}
\ 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..ce92a989
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/PolicyDocumentTest.java
@@ -0,0 +1,107 @@
+package com.salesforce.multicloudj.iam.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Unit tests for PolicyDocument builder pattern.
+ */
+public class PolicyDocumentTest {
+
+    @Test
+    public void testPolicyDocumentBuilder() {
+        PolicyDocument policy = PolicyDocument.builder()
+            .version("2024-01-01")
+            .statement("StorageAccess")
+                .effect("Allow")
+                .addAction("storage:GetObject")
+                .addAction("storage:PutObject")
+                .addPrincipal("arn:aws:iam::123456789012:user/ExampleUser")
+                .addResource("storage://my-bucket/*")
+                .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .endStatement()
+            .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()
+            .statement("ReadAccess")
+                .effect("Allow")
+                .addAction("storage:GetObject")
+                .addResource("storage://my-bucket/*")
+            .endStatement()
+            .statement("WriteAccess")
+                .effect("Allow")
+                .addAction("storage:PutObject")
+                .addResource("storage://my-bucket/*")
+            .endStatement()
+            .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")
+            .addAction("storage:GetObject")
+            .addResource("storage://my-bucket/*")
+            .build();
+
+        PolicyDocument policy = PolicyDocument.builder()
+            .addStatement(statement)
+            .build();
+
+        assertEquals(1, policy.getStatements().size());
+        assertEquals("TestStatement", policy.getStatements().get(0).getSid());
+    }
+
+    @Test
+    public void testEmptyPolicyThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            PolicyDocument.builder().build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutEffectThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            PolicyDocument.builder()
+                .statement("TestStatement")
+                    .addAction("storage:GetObject")
+                .endStatement()
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutActionsThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            PolicyDocument.builder()
+                .statement("TestStatement")
+                    .effect("Allow")
+                .endStatement()
+                .build();
+        });
+    }
+}
\ 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..ef1fef0d
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/StatementTest.java
@@ -0,0 +1,174 @@
+package com.salesforce.multicloudj.iam.model;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * Unit tests for Statement builder pattern and functionality.
+ */
+public class StatementTest {
+
+    @Test
+    public void testStatementBuilder() {
+        Statement statement = Statement.builder()
+            .sid("TestStatement")
+            .effect("Allow")
+            .addAction("storage:GetObject")
+            .addAction("storage:PutObject")
+            .addResource("storage://my-bucket/*")
+            .addPrincipal("arn:aws:iam::123456789012:user/TestUser")
+            .addCondition("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")
+            .addAction("storage:DeleteObject")
+            .addResource("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 testStatementBuilderMultipleActions() {
+        List expectedActions = Arrays.asList("storage:GetObject", "storage:PutObject", "storage:ListObjects");
+
+        Statement statement = Statement.builder()
+            .sid("MultiActionStatement")
+            .effect("Allow")
+            .addAction("storage:GetObject")
+            .addAction("storage:PutObject")
+            .addAction("storage:ListObjects")
+            .addResource("storage://multi-action-bucket/*")
+            .build();
+
+        assertEquals(expectedActions, statement.getActions());
+    }
+
+    @Test
+    public void testStatementBuilderMultipleResources() {
+        List expectedResources = Arrays.asList("storage://bucket1/*", "storage://bucket2/*");
+
+        Statement statement = Statement.builder()
+            .sid("MultiResourceStatement")
+            .effect("Allow")
+            .addAction("storage:GetObject")
+            .addResource("storage://bucket1/*")
+            .addResource("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")
+            .addAction("storage:GetObject")
+            .addResource("storage://shared-bucket/*")
+            .addPrincipal("arn:aws:iam::123456789012:user/User1")
+            .addPrincipal("arn:aws:iam::123456789012:user/User2")
+            .build();
+
+        assertEquals(expectedPrincipals, statement.getPrincipals());
+    }
+
+    @Test
+    public void testStatementBuilderMultipleConditions() {
+        Statement statement = Statement.builder()
+            .sid("MultiConditionStatement")
+            .effect("Allow")
+            .addAction("storage:GetObject")
+            .addResource("storage://conditional-bucket/*")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .addCondition("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 testStatementBuilderDenyEffect() {
+        Statement statement = Statement.builder()
+            .sid("DenyStatement")
+            .effect("Deny")
+            .addAction("*")
+            .addResource("storage://restricted-bucket/*")
+            .build();
+
+        assertEquals("Deny", statement.getEffect());
+        assertEquals(Arrays.asList("*"), statement.getActions());
+    }
+
+    @Test
+    public void testStatementWithoutSid() {
+        Statement statement = Statement.builder()
+            .effect("Allow")
+            .addAction("storage:GetObject")
+            .addResource("storage://no-sid-bucket/*")
+            .build();
+
+        assertNull(statement.getSid());
+        assertEquals("Allow", statement.getEffect());
+    }
+
+    @Test
+    public void testEmptyStatementThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            Statement.builder().build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutEffectThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            Statement.builder()
+                .sid("NoEffectStatement")
+                .addAction("storage:GetObject")
+                .addResource("storage://test-bucket/*")
+                .build();
+        });
+    }
+
+    @Test
+    public void testStatementWithoutActionsThrowsException() {
+        assertThrows(IllegalArgumentException.class, () -> {
+            Statement.builder()
+                .sid("NoActionsStatement")
+                .effect("Allow")
+                .addResource("storage://test-bucket/*")
+                .build();
+        });
+    }
+}
\ 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..2d37a529
--- /dev/null
+++ b/iam/iam-client/src/test/java/com/salesforce/multicloudj/iam/model/TrustConfigurationTest.java
@@ -0,0 +1,276 @@
+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.*;
+
+/**
+ * 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")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "service-account@my-project.iam.gserviceaccount.com",
+            "another-sa@different-project.iam.gserviceaccount.com"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderAliCloudPrincipals() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("1234567890123456")  // AliCloud account ID
+            .addTrustedPrincipal("acs:ram::1234567890123456:user/AliUser")  // AliCloud RAM user
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "1234567890123456",
+            "acs:ram::1234567890123456:user/AliUser"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+    }
+
+    @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 testTrustConfigurationBuilderIgnoreNullAndEmptyPrincipals() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addTrustedPrincipal(null)
+            .addTrustedPrincipal("")
+            .addTrustedPrincipal("   ")  // whitespace only
+            .addTrustedPrincipal("arn:aws:iam::987654321098:root")
+            .build();
+
+        List expectedPrincipals = Arrays.asList(
+            "arn:aws:iam::123456789012:root",
+            "arn:aws:iam::987654321098:root"
+        );
+
+        assertEquals(expectedPrincipals, trustConfig.getTrustedPrincipals());
+    }
+
+    @Test
+    public void testTrustConfigurationBuilderIgnoreNullConditions() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .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();
+
+        Map> conditions = trustConfig.getConditions();
+        assertEquals(1, conditions.size());
+        assertTrue(conditions.containsKey("StringEquals"));
+        assertEquals(1, conditions.get("StringEquals").size());
+        assertEquals("us-west-2", conditions.get("StringEquals").get("aws:RequestedRegion"));
+    }
+
+    @Test
+    public void testTrustConfigurationEquality() {
+        TrustConfiguration trustConfig1 = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        TrustConfiguration trustConfig2 = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        TrustConfiguration trustConfig3 = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::987654321098:root")
+            .addCondition("StringEquals", "aws:RequestedRegion", "us-west-2")
+            .build();
+
+        assertEquals(trustConfig1, trustConfig2);
+        assertNotEquals(trustConfig1, trustConfig3);
+        assertEquals(trustConfig1.hashCode(), trustConfig2.hashCode());
+    }
+
+    @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 testTrustConfigurationImmutable() {
+        TrustConfiguration trustConfig = TrustConfiguration.builder()
+            .addTrustedPrincipal("arn:aws:iam::123456789012:root")
+            .build();
+
+        List principals = trustConfig.getTrustedPrincipals();
+        Map> conditions = trustConfig.getConditions();
+
+        // Modifying returned lists/maps should not affect the original
+        principals.add("new-principal");
+        conditions.put("NewOperator", Map.of("key", "value"));
+
+        // Original should remain unchanged
+        assertEquals(1, trustConfig.getTrustedPrincipals().size());
+        assertEquals(0, trustConfig.getConditions().size());
+    }
+}
\ 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 ae33fb07..e7018395 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
     
 
     
+        iam
         blob
         docstore
         examples