A zero-dependency CLI tool for validating SCIM 2.0 User, Group, Agent, and AgenticApplication payloads (RFC 7643/7644)
Project description
scim-sanity
Catch SCIM integration bugs before they hit production
A lightweight CLI linter for SCIM 2.0 payloads – now with early support for provisioning AI agents and agentic applications
Works offline · Pure Python standard library · No external dependencies required.
Built for the Agentic Future
The rapid growth of AI agents requires robust identity management distinct from traditional users. The October 2025 IETF draft introduces dedicated Agent and AgenticApplication resource types in SCIM, enabling standardized provisioning, ownership tracking, and lifecycle control for non-human workloads.
scim-sanity adds early validation for these schemas, helping developers and IAM teams adopt the new standard confidently and avoid integration issues in multi-agent environments.
Why scim-sanity?
SCIM (System for Cross-domain Identity Management) integrations are notoriously tricky. Common mistakes like missing required fields, setting immutable attributes, or invalid PATCH operations can cause silent failures or break production systems. scim-sanity validates your SCIM payloads locally before they hit your API, catching these issues early.
Features
✅ Zero dependencies - Works with Python standard library only (optional Click for better CLI)
✅ SCIM 2.0 compliant - Validates against RFC 7643 and RFC 7644
✅ Agent extension support - Validates Agent and AgenticApplication resources (draft-abbey-scim-agent-extension-00)
✅ Comprehensive checks - Catches 15+ common integration errors
✅ Color output - Beautiful, readable error messages with line numbers
✅ PATCH support - Validates both full resources and PATCH operations
✅ Enterprise extension - Supports enterprise user extension schema
Installation
Using pipx (recommended)
pipx install scim-sanity
Using pip
pip install scim-sanity
From source
git clone https://github.com/thomaselliottbetz/scim-sanity.git
cd scim-sanity
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -e .
Verifying Installation
After installation, verify that scim-sanity is working correctly:
Option 1: Using the command (if installed via pip/pipx or with venv activated)
scim-sanity --help
Option 2: Using Python module (works from anywhere)
python3 -m scim_sanity --help
Quick test:
# Test with a valid user resource
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"userName":"test@example.com"}' | python3 -m scim_sanity --stdin
# Expected output: ✅ Valid SCIM resource
# Test with an invalid resource (missing userName)
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"]}' | python3 -m scim_sanity --stdin
# Expected output: Error about missing userName
# Test with an Agent resource
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Agent"],"name":"test-agent"}' | python3 -m scim_sanity --stdin
# Expected output: ✅ Valid SCIM resource
Usage
scim-sanity can be run in several ways depending on your installation method:
Running the Tool
If installed via pip/pipx or with virtual environment activated:
scim-sanity [options] [file]
Using Python module (always works):
python3 -m scim_sanity [options] [file]
# or
python -m scim_sanity [options] [file]
Command Options
<file>- Path to a JSON file containing a SCIM resource or PATCH operation--patch- Validate the input as a SCIM PATCH operation instead of a full resource--stdin- Read JSON from standard input instead of a file-h, --help- Show help message and exit
Basic Usage Examples
Validate a SCIM resource file
# Validate a User resource
scim-sanity user.json
# Validate a Group resource
scim-sanity group.json
# Validate an Agent resource (auto-detected from schema URI)
scim-sanity agent.json
# Validate an AgenticApplication resource (auto-detected from schema URI)
scim-sanity agentic-app.json
# Using Python module
python3 -m scim_sanity user.json
Validate a PATCH operation
scim-sanity --patch patch.json
# Using Python module
python3 -m scim_sanity --patch patch.json
Validate from stdin
# Validate a User resource from stdin
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"userName":"user@example.com"}' | scim-sanity --stdin
# Validate a PATCH operation from stdin
echo '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],"Operations":[{"op":"replace","path":"displayName","value":"New Name"}]}' | scim-sanity --stdin --patch
# Pipe from another command
curl -s https://api.example.com/user/123 | scim-sanity --stdin
Common Workflows
Pre-commit Validation
Validate SCIM payloads before committing or deploying:
# Validate all JSON files in a directory
for file in payloads/*.json; do
echo "Validating $file..."
scim-sanity "$file" || exit 1
done
CI/CD Integration
Use in your CI pipeline to catch SCIM errors early:
# In your CI script
if ! scim-sanity user-payload.json; then
echo "SCIM validation failed!"
exit 1
fi
Testing API Responses
Validate responses from your SCIM API:
# Test a GET response
curl -s https://api.example.com/scim/v2/Users/123 | scim-sanity --stdin
# Test a POST request body before sending
scim-sanity new-user.json && curl -X POST https://api.example.com/scim/v2/Users -d @new-user.json
Interactive Development
Quick validation while developing:
# Validate and see errors immediately
scim-sanity my-payload.json
# If valid, proceed with API call
scim-sanity my-payload.json && curl -X POST ... -d @my-payload.json
Exit Codes
The tool uses standard exit codes for scripting:
0- Validation passed (resource is valid)1- Validation failed (errors found) or an error occurred
Use exit codes in scripts:
if scim-sanity payload.json; then
echo "Payload is valid, proceeding..."
# Continue with your workflow
else
echo "Validation failed, stopping..."
exit 1
fi
Pre-commit Integration
Automatically validate SCIM payloads on every commit to enforce compliance in developer workflows. This is ideal for Infrastructure as Code (IaC) repositories, provisioning templates, security automation pipelines, and any codebase managing SCIM resources.
Installation
-
Install pre-commit:
pip install pre-commit
-
Install the git hook:
pre-commit install -
Add
.pre-commit-config.yamlto your repository root:
# Pre-commit hook configuration for scim-sanity
# See https://pre-commit.com for more information
repos:
- repo: local
hooks:
- id: scim-sanity
name: Validate SCIM resources with scim-sanity
entry: python -m scim_sanity
language: system
types: [json]
exclude: |
(?x)^(
.*/node_modules/.*|
.*/\.venv/.*|
.*/venv/.*|
.*/ENV/.*|
.*/env/.*|
.*/\.tox/.*|
.*/dist/.*|
.*/build/.*|
.*package\.json$|
.*package-lock\.json$|
.*tsconfig.*\.json$|
.*jsconfig\.json$|
.*\.pre-commit-config\.yaml$|
.*\.gitignore$|
.*\.vscode/.*|
.*\.idea/.*|
.*\.pytest_cache/.*|
.*\.mypy_cache/.*|
.*\.coverage$|
.*coverage\.json$
)$
pass_filenames: true
require_serial: true
always_run: false
stages: [commit]
How It Works
The hook automatically validates all JSON files on commit, excluding common configuration files and dependency directories. Files without SCIM schema URNs will be validated by scim-sanity and will fail if they don't conform to SCIM specifications, ensuring only valid SCIM resources are committed.
On valid commit:
$ git commit -m "Add new user resource"
scim-sanity................................................................Passed
[main abc1234] Add new user resource
On invalid commit:
$ git commit -m "Add invalid user resource"
scim-sanity................................................................Failed
- hook id: scim-sanity
- exit code: 1
Found 1 error(s):
❌ Missing required attribute: 'userName' (schema: urn:ietf:params:scim:schemas:core:2.0:User) at userName
Pre-commit.ci Integration
The pre-commit.ci badge at the top of this README shows the status of pre-commit checks on pull requests. To enable pre-commit.ci for this repository:
- Enable the service at https://pre-commit.ci (sign in with GitHub)
- Install the GitHub App on this repository
- Pre-commit.ci will automatically run hooks on pull requests
Note: The badge will show a "not found" status until the service is enabled and has run at least once.
Understanding Output
Valid Resource
When validation passes, you'll see:
✅ Valid SCIM resource
or for PATCH operations:
✅ Valid PATCH operation
Invalid Resource
When validation fails, errors are displayed with clear messages:
Found 3 error(s):
❌ Missing required attribute: 'userName' (schema: urn:ietf:params:scim:schemas:core:2.0:User) at userName
❌ Immutable attribute 'id' should not be set by client (mutability: readOnly) at id
❌ Attribute 'displayName' has null value. Use PATCH 'remove' operation to clear attributes instead at displayName
Each error message includes:
- Error type - What went wrong
- Location - The attribute path where the error occurred
- Guidance - How to fix the issue
Error Messages Explained
- Missing required attribute - A required field for the resource type is missing
- Immutable attribute - You're trying to set a read-only field (like
idormeta) - Null value - Using
nullto clear a value (use PATCHremoveinstead) - Invalid schema - Unknown or invalid schema URN
- Invalid structure - Data doesn't match expected SCIM structure (e.g., multi-valued attribute not an array)
Validation Checks
scim-sanity performs the following checks:
Required Attributes
- ✅ Ensures
userNameis present for User resources - ✅ Ensures
displayNameis present for Group resources - ✅ Ensures
nameis present and non-empty for Agent resources - ✅ Ensures
nameis present and non-empty for AgenticApplication resources - ✅ Validates all required schema attributes
Schema Validation
- ✅ Validates schema URNs (core User, Group, Agent, AgenticApplication, enterprise extension)
- ✅ Auto-detects resource type from schema URIs (no flags needed)
- ✅ Rejects unknown or invalid schema URNs
- ✅ Ensures
schemasfield is present and non-empty
Mutability Rules
- ✅ Flags immutable attributes (e.g.,
id,meta) being set by client - ✅ Validates read-only attributes are not modified
PATCH Operations
- ✅ Validates PATCH operation structure
- ✅ Ensures valid
opvalues (add,remove,replace) - ✅ Checks for duplicate paths in operations
- ✅ Validates required fields per operation type
Data Semantics
- ✅ Rejects
nullvalues (use PATCHremoveinstead) - ✅ Validates complex attribute structures
- ✅ Validates multi-valued attributes are arrays
Examples
Valid User Resource
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "john.doe@example.com",
"name": {
"givenName": "John",
"familyName": "Doe"
},
"emails": [
{
"value": "john.doe@example.com",
"type": "work",
"primary": true
}
],
"active": true
}
Valid Group Resource
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"],
"displayName": "Engineering Team",
"members": [
{
"value": "user-id-123",
"display": "John Doe",
"type": "User"
}
]
}
Valid PATCH Operation
{
"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
"Operations": [
{
"op": "replace",
"path": "displayName",
"value": "New Name"
},
{
"op": "add",
"path": "emails",
"value": [
{
"value": "newemail@example.com",
"type": "work"
}
]
}
]
}
Valid User with Enterprise Extension
{
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User"
],
"userName": "manager@example.com",
"name": {
"givenName": "Jane",
"familyName": "Manager"
},
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
"employeeNumber": "EMP-001",
"department": "Engineering",
"manager": {
"value": "ceo-id",
"displayName": "CEO"
}
}
}
Valid Agent Resource
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Agent"],
"name": "research-assistant",
"displayName": "Research Assistant",
"agentType": "Assistant",
"active": true,
"description": "An AI research assistant agent"
}
Minimal Agent Resource (only name is required):
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:Agent"],
"name": "helpdesk-bot"
}
Valid AgenticApplication Resource
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:AgenticApplication"],
"name": "assistant-platform",
"displayName": "Assistant Platform",
"description": "A platform for AI research agents",
"active": true
}
Minimal AgenticApplication Resource (only name is required):
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:AgenticApplication"],
"name": "my-agentic-app"
}
Invalid Examples (Common Mistakes)
Missing Required Field
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"]
// Missing userName - will fail validation
}
Error: ❌ Missing required attribute: 'userName'
Setting Immutable Attribute
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "user@example.com",
"id": "12345" // ❌ Cannot set id - it's read-only
}
Error: ❌ Immutable attribute 'id' should not be set by client
Using Null Values
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "user@example.com",
"displayName": null // ❌ Use PATCH remove instead
}
Error: ❌ Attribute 'displayName' has null value. Use PATCH 'remove' operation to clear attributes instead
Invalid Multi-valued Attribute
{
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName": "user@example.com",
"emails": "not-an-array" // ❌ emails must be an array
}
Error: ❌ Multi-valued attribute 'emails' must be an array
Troubleshooting
Command not found
If you get command not found: scim-sanity:
-
Check if virtual environment is activated (if installed from source):
source venv/bin/activate # or .venv/bin/activate
-
Use Python module instead:
python3 -m scim_sanity --help
-
Verify installation:
pip show scim-sanity # Should show package info
File not found errors
Make sure you're providing the correct path:
# Use absolute or relative paths
scim-sanity ./path/to/file.json
scim-sanity /absolute/path/to/file.json
JSON parsing errors
If you see "Invalid JSON" errors:
- Verify your file is valid JSON (use
jqor an online JSON validator) - Check for trailing commas or syntax errors
- Ensure the file encoding is UTF-8
Validation passes but API still rejects
scim-sanity validates SCIM 2.0 compliance, but your API might have:
- Additional custom validation rules
- Different schema extensions
- Server-specific requirements
Always test with your actual API endpoint as well.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development
# Clone the repository
git clone https://github.com/thomaselliottbetz/scim-sanity.git
cd scim-sanity
# Create virtual environment
python -m venv venv
source venv/bin/activate
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linter (if configured)
# flake8 scim_sanity tests
License
This project is licensed under the MIT License - see the LICENSE file for details.
Agent and AgenticApplication Support
Overview
scim-sanity now supports validation of Agent and AgenticApplication resources as defined in the IETF draft extension "SCIM Agents and Agentic Applications Extension" (draft-abbey-scim-agent-extension-00). This extension enables SCIM-based provisioning and management of AI agents and agentic applications as first-class identities.
Terminology Note
Throughout this documentation, you may see:
- AgenticApplication (one word) when referring to the schema name or technical identifier
- Agentic Applications (two words) when referencing the IETF draft extension title
- agentic applications (lowercase) in descriptive prose
All refer to the same resource type - the variation is intentional for readability and technical accuracy.
Why Agent Support?
With the rise of AI agents and agentic applications, organizations need to manage these workloads as distinct identities separate from traditional users. The IETF draft extension provides:
- Standardized schema for agent identity management via SCIM
- Separation of concerns - Agents are distinct from Users/Groups
- Interoperability - Enables SCIM-based agent discovery and provisioning
- Unified management - Reuses existing SCIM infrastructure
Common use cases include:
- Provisioning AI assistants and chatbots as SCIM resources
- Managing access and entitlements for agent workloads
- Tracking agent ownership and accountability
- Integrating agent identity management with existing IAM systems
Key Features
- Auto-detection: Resource type is automatically detected from schema URIs - no special flags needed
- Minimal validation: Only validates required fields (
namefor Agents/AgenticApplications) per the draft specification - Schema compliance: Validates against the complete Agent and AgenticApplication schemas
- Backward compatible: Existing User/Group validation continues to work unchanged
Schema URIs
- Agent:
urn:ietf:params:scim:schemas:core:2.0:Agent - AgenticApplication:
urn:ietf:params:scim:schemas:core:2.0:AgenticApplication
Validation Rules
For Agent resources:
nameattribute is REQUIRED and must be non-empty- All other attributes (displayName, agentType, active, etc.) are optional
- Validates mutability rules (e.g., subject, owners are read-only)
For AgenticApplication resources:
nameattribute is REQUIRED and must be non-empty- All other attributes (displayName, description, active) are optional
Example Usage
# Validate an Agent resource
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Agent"],"name":"my-agent"}' | scim-sanity --stdin
# Validate an AgenticApplication resource
echo '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:AgenticApplication"],"name":"my-app"}' | scim-sanity --stdin
# Validate from file
scim-sanity agent.json
scim-sanity agentic-application.json
The validator automatically detects the resource type from the schema URI, so you use the same command-line interface for all resource types.
References
- RFC 7643 - SCIM: Core Schema
- RFC 7644 - SCIM: Protocol
- draft-abbey-scim-agent-extension-00 - SCIM Agents and Agentic Applications Extension
Roadmap
- Enhanced validation for agent-specific attributes (owner, capabilities, subject)
- Potential integration as a tool in agent frameworks and MCP servers
- Support for evolving non-human identity standards
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file scim_sanity-0.2.0.tar.gz.
File metadata
- Download URL: scim_sanity-0.2.0.tar.gz
- Upload date:
- Size: 25.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d0d5479d0925a0bbf9ad79d95c793528c23784ffedfcb2c231f76d913d16d579
|
|
| MD5 |
09a11e89f7cdb283ed8326b11cf3408e
|
|
| BLAKE2b-256 |
1d0ba860d1cf5ef6a31a3935b3eecce9fe691e9fbf31af2c2bbcd6c4d5a70e8d
|
File details
Details for the file scim_sanity-0.2.0-py3-none-any.whl.
File metadata
- Download URL: scim_sanity-0.2.0-py3-none-any.whl
- Upload date:
- Size: 17.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1c71ac21d5cca8b375aea5c6e1266d8739586856a2c0bfab8308107000d1e7a
|
|
| MD5 |
7c7df3a7ea5b11b31c393c93a51be397
|
|
| BLAKE2b-256 |
a797986d32ecab5416027fa741e6c3c7c3f38ce4ab6e152515120d5bfd2d8b00
|