Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Architecture

The SCIM Server follows a clean trait-based architecture with clear separation of concerns designed for maximum composability and extensibility.

Component Architecture

The library is built around composable traits that you implement for your specific needs:

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│  Client Layer   │    │   SCIM Server    │    │ Resource Layer  │
│                 │    │                  │    │                 │
│  • MCP AI       │───▶│  • Operations    │───▶│ ResourceProvider│
│  • Web Framework│    │  • Multi-tenant  │    │      trait      │
│  • Custom       │    │  • Type Safety   │    │                 │
└─────────────────┘    └──────────────────┘    └─────────────────┘
                              │                          │
                              ▼                          ▼
                       ┌──────────────────┐    ┌─────────────────┐
                       │ Schema System    │    │ Storage Layer   │
                       │                  │    │                 │
                       │ • SchemaRegistry │    │ StorageProvider │
                       │ • Validation     │    │      trait      │
                       │ • Value Objects  │    │  • In-Memory    │
                       │ • Extensions     │    │  • Database     │
                       └──────────────────┘    │  • Custom       │
                                               └─────────────────┘

Layer Responsibilities

Client Layer: Your integration points - compose these components into web endpoints, AI tools, or custom applications.

SCIM Server: Orchestration component that coordinates resource operations using your provider implementations.

Resource Layer: ResourceProvider trait - implement this interface for your data model, or use the provided StandardResourceProvider for common scenarios.

Schema System: Schema registry and validation components - extend with custom schemas and value objects.

Storage Layer: StorageProvider trait - use the provided InMemoryStorage for development, or connect to any database or custom backend.

Core Traits

ResourceProvider

Your main integration point for SCIM resource operations:

#![allow(unused)]
fn main() {
pub trait ResourceProvider {
    type Error: std::error::Error + Send + Sync + 'static;

    async fn create_resource(
        &self,
        resource_type: &str,
        data: Value,
        context: &RequestContext,
    ) -> Result<Resource, Self::Error>;

    async fn get_resource(
        &self,
        resource_type: &str,
        id: &str,
        context: &RequestContext,
    ) -> Result<Option<Resource>, Self::Error>;

    // ... other CRUD operations
}
}

Implementation Options:

  • Use StandardResourceProvider<S> with any StorageProvider for typical use cases
  • Implement directly for custom business logic and data models
  • Wrap existing services or databases

StorageProvider

Pure data persistence abstraction:

#![allow(unused)]
fn main() {
pub trait StorageProvider: Send + Sync {
    type Error: std::error::Error + Send + Sync + 'static;

    async fn put(&self, key: StorageKey, data: Value) -> Result<Value, Self::Error>;
    async fn get(&self, key: StorageKey) -> Result<Option<Value>, Self::Error>;
    async fn delete(&self, key: StorageKey) -> Result<bool, Self::Error>;
    async fn list(&self, prefix: StoragePrefix) -> Result<Vec<Value>, Self::Error>;
}
}

Implementation Options:

  • Use InMemoryStorage for development and testing
  • Implement for your database (PostgreSQL, MongoDB, etc.)
  • Connect to cloud storage or external APIs

Value Objects

Type-safe SCIM attribute handling:

#![allow(unused)]
fn main() {
pub trait ValueObject: Debug + Send + Sync {
    fn attribute_type(&self) -> AttributeType;
    fn to_json(&self) -> ValidationResult<Value>;
    fn validate_against_schema(&self, definition: &AttributeDefinition) -> ValidationResult<()>;
    // ...
}

pub trait SchemaConstructible: ValueObject + Sized {
    fn from_schema_and_value(
        definition: &AttributeDefinition,
        value: &Value,
    ) -> ValidationResult<Self>;
    // ...
}
}

Extension Points:

  • Create custom value objects for domain-specific attributes
  • Implement validation logic for business rules
  • Support for complex multi-valued attributes

Multi-Tenant Architecture

The library provides several components for multi-tenant systems:

TenantResolver

Maps authentication credentials to tenant context:

#![allow(unused)]
fn main() {
pub trait TenantResolver: Send + Sync {
    type Error: std::error::Error + Send + Sync + 'static;

    async fn resolve_tenant(&self, credential: &str) -> Result<TenantContext, Self::Error>;
}
}

RequestContext

Carries tenant and request information through all operations:

#![allow(unused)]
fn main() {
pub struct RequestContext {
    pub request_id: String,
    tenant_context: Option<TenantContext>,
}
}

Tenant Isolation

  • All ResourceProvider operations include RequestContext
  • Storage keys automatically include tenant ID
  • Schema validation respects tenant-specific extensions

Schema System Architecture

SchemaRegistry

Central registry for SCIM schemas:

  • Loads and validates RFC 7643 core schemas
  • Supports custom schema extensions
  • Provides validation services for all operations

Dynamic Value Objects

  • Runtime creation from schema definitions
  • Type-safe attribute handling
  • Extensible factory pattern for custom types

Extension Model

  • Custom resource types beyond User/Group
  • Organization-specific attributes
  • Maintains SCIM compliance and interoperability

Concurrency Control

ETag-Based Versioning

Built into the core architecture:

  • Automatic version generation from resource content
  • Conditional operations (If-Match, If-None-Match)
  • Conflict detection and resolution
  • Production-ready optimistic locking

Version-Aware Operations

All resource operations support conditional execution:

#![allow(unused)]
fn main() {
// Conditional update with version check
let result = provider.conditional_update(
    "User", 
    &user_id, 
    updated_data, 
    &expected_version, 
    &context
).await?;

match result {
    ConditionalResult::Success(resource) => // Update succeeded
    ConditionalResult::PreconditionFailed => // Version conflict
}
}

Integration Patterns

Web Framework Integration

Components work with any HTTP framework:

  1. Extract SCIM request details
  2. Create RequestContext with tenant info
  3. Call appropriate ScimServer operations
  4. Format responses per SCIM specification

AI Agent Integration

Model Context Protocol (MCP) components:

  1. Expose SCIM operations as discoverable tools
  2. Structured schemas for AI understanding
  3. Error handling designed for AI decision making
  4. Multi-tenant aware tool descriptions

Custom Client Integration

Direct component usage:

  1. Implement ResourceProvider for your data model
  2. Choose appropriate StorageProvider
  3. Configure schema extensions as needed
  4. Build custom API layer or integration logic

Performance Considerations

Async-First Design

  • All I/O operations are async
  • Non-blocking concurrent operations
  • Efficient resource utilization

Minimal Allocations

  • Zero-copy JSON processing where possible
  • Efficient value object system
  • Smart caching in schema registry

Scalability Features

  • Pluggable storage for horizontal scaling
  • Multi-tenant isolation for SaaS platforms
  • Connection pooling support through storage traits