Metadata-Version: 2.4
Name: miso-client
Version: 0.2.0
Summary: Python client SDK for AI Fabrix authentication, authorization, and logging
Home-page: https://github.com/aifabrix/miso-client-python
Author: AI Fabrix Team
Author-email: AI Fabrix Team <team@aifabrix.ai>
Maintainer-email: AI Fabrix Team <team@aifabrix.ai>
License-Expression: MIT
Project-URL: Homepage, https://github.com/aifabrix/miso-client-python
Project-URL: Documentation, https://docs.aifabrix.ai/miso-client-python
Project-URL: Repository, https://github.com/aifabrix/miso-client-python
Project-URL: Issues, https://github.com/aifabrix/miso-client-python/issues
Keywords: authentication,authorization,rbac,jwt,redis,logging,aifabrix,miso
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Security
Classifier: Topic :: System :: Logging
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.0.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: redis[hiredis]>=5.0.0
Requires-Dist: PyJWT>=2.8.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4.3; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.1; extra == "dev"
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: isort>=5.12.0; extra == "dev"
Requires-Dist: mypy>=1.5.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

# AI Fabrix Miso Client SDK (Python)

[![PyPI version](https://badge.fury.io/py/miso-client.svg)](https://badge.fury.io/py/miso-client)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

The **AI Fabrix Miso Client SDK** provides authentication, authorization, and logging for Python applications integrated with the AI Fabrix platform.

## ✨ Benefits

### 🔐 Enterprise Security

**SSO and Federated Identity**
- Single Sign-On (SSO) with Keycloak
- OAuth 2.0 and OpenID Connect (OIDC) support
- Multi-factor authentication (MFA) ready
- Social login integration (Google, Microsoft, etc.)

**Centralized Access Control**
- Role-based access control (RBAC)
- Fine-grained permissions
- Dynamic policy enforcement
- Attribute-based access control (ABAC)

**API Security**
- JWT token validation
- API key authentication
- Token revocation support
- Secure token storage
- Data encryption/decryption (AES-256-GCM)

### 📊 Compliance & Audit

**ISO 27001 Compliance**
- Comprehensive audit trails for all user actions
- Data access logging and monitoring
- Security event tracking
- Accountability and non-repudiation

**Regulatory Compliance**
- GDPR-ready data protection
- HIPAA-compliant audit logging
- SOC 2 audit trail requirements
- Industry-standard security controls

**Audit Capabilities**
- Real-time audit event logging
- Immutable audit records
- Forensic analysis support
- Compliance reporting automation

### ⚡ Performance & Scalability

**Intelligent Caching**
- Redis-based role and permission caching
- Generic cache service with Redis and in-memory fallback
- Configurable cache TTL (default: 15 minutes)
- Automatic cache invalidation
- Fallback to controller when Redis unavailable

**High Availability**
- Automatic failover to controller
- Redundant infrastructure support
- Load balancing compatible
- Zero-downtime deployments

**Optimized Network**
- Efficient API calls with caching
- Batch operations support
- Connection pooling
- Minimal latency

### 🛠️ Developer Experience

**Easy Integration**
- Progressive activation (6-step setup)
- Works with any framework (FastAPI, Django, Flask, Starlette)
- Python 3.8+ support with full type hints
- Async/await support throughout

**Flexible Configuration**
- Environment-based configuration
- Support for dev, test, and production environments
- Docker and Kubernetes ready
- CI/CD friendly

**Observability**
- Centralized logging with correlation IDs
- Performance tracking and metrics
- Error tracking and debugging
- Health monitoring

---

## 🚀 Quick Start

Get your application secured in 30 seconds.

### Step 1: Install

```bash
pip install miso-client
```

### Step 2: Create `.env`

```bash
MISO_CLIENTID=ctrl-dev-my-app
MISO_CLIENTSECRET=your-secret
MISO_CONTROLLER_URL=http://localhost:3000
REDIS_HOST=localhost
```

### Step 3: Use It

```python
from miso_client import MisoClient, load_config

client = MisoClient(load_config())
await client.initialize()

is_valid = await client.validate_token(token)
```

**That's it!** You now have authentication, roles, and logging.

→ [Full Getting Started Guide](docs/getting-started.md)

---

### Infrastructure Setup

**First time?** You'll need Keycloak and Miso Controller running.

Use the [AI Fabrix Builder](https://github.com/esystemsdev/aifabrix-builder/blob/main/docs/QUICK-START.md):

```bash
# Start infrastructure (Postgres, Redis)
aifabrix up

# Install Keycloak for authentication
aifabrix create keycloak --port 8082 --database --template platform
aifabrix build keycloak
aifabrix run keycloak

# Install Miso Controller
aifabrix create miso-controller --port 3000 --database --redis --template platform
aifabrix build miso-controller
aifabrix run miso-controller
```

→ [Infrastructure Guide](https://github.com/esystemsdev/aifabrix-builder/blob/main/docs/INFRASTRUCTURE.md)

**Already have Keycloak and Controller?** Use the Quick Start above.

---

## 📚 Documentation

**What happens:** Your app validates user tokens from Keycloak.

```python
from miso_client import MisoClient, load_config

# Create client (loads from .env automatically)
client = MisoClient(load_config())
await client.initialize()

# Get token from request (helper method)
token = client.get_token(req)

if token:
    is_valid = await client.validate_token(token)
    if is_valid:
        user = await client.get_user(token)
        print('User:', user)
```

**Where to get tokens?** Users authenticate via Keycloak, then your app receives JWTs in the `Authorization` header.

→ [Complete authentication example](examples/step-3-authentication.py)

---

### Step 4: Activate RBAC (Roles)

**What happens:** Check user roles to control access. Roles are cached in Redis for performance.

```python
from miso_client import MisoClient, load_config

# Build on Step 3 - add Redis in .env file
client = MisoClient(load_config())
await client.initialize()

token = client.get_token(req)

# Check if user has role
is_admin = await client.has_role(token, 'admin')
roles = await client.get_roles(token)

# Gate features by role
if is_admin:
    # Show admin panel
    pass
```

**Pro tip:** Without Redis, checks go to the controller. Add Redis to cache role lookups (15-minute default TTL).

→ [Complete RBAC example](examples/step-4-rbac.py)  
→ [AI Fabrix Builder Quick Start](https://github.com/esystemsdev/aifabrix-builder/blob/main/docs/QUICK-START.md)

---

### Step 5: Activate Logging

**What happens:** Application logs are sent to the Miso Controller with client token authentication.

```python
from miso_client import MisoClient, load_config

# Client token is automatically managed - no API key needed
client = MisoClient(load_config())
await client.initialize()

token = client.get_token(req)
user = await client.get_user(token)

# Log messages
await client.log.info('User accessed dashboard', {'userId': user.id if user else None})
await client.log.error('Operation failed', {'error': str(err)})
await client.log.warn('Unusual activity', {'details': '...'})
```

**What happens to logs?** They're sent to the Miso Controller for centralized monitoring and analysis. Client token is automatically included.

→ [Complete logging example](examples/step-5-logging.py)  
→ [Logging Reference](docs/api-reference.md#logger-service)

---

### Step 6: Activate Audit

**What happens:** Create audit trails for compliance and security monitoring.

```python
from miso_client import MisoClient, load_config

# Complete configuration (all in .env)
client = MisoClient(load_config())
await client.initialize()

token = client.get_token(req)
is_valid = await client.validate_token(token)
can_edit = await client.has_permission(token, 'edit:content')
user = await client.get_user(token)

# Audit: User actions
await client.log.audit('user.login', 'authentication', {
    'userId': user.id if user else None,
    'ip': req.get('ip', ''),
    'userAgent': req.get('headers', {}).get('user-agent', ''),
})

# Audit: Content changes
await client.log.audit('post.created', 'content', {
    'userId': user.id if user else None,
    'postId': 'post-123',
    'postTitle': req.get('body', {}).get('title', ''),
})

# Audit: Permission checks
await client.log.audit('access.denied', 'authorization', {
    'userId': user.id if user else None,
    'requiredPermission': 'edit:content',
    'resource': 'posts',
})
```

**What to audit:** Login/logout, permission checks, content creation/deletion, role changes, sensitive operations.

→ [Complete audit example](examples/step-6-audit.py)  
→ [Best Practices](docs/getting-started.md#common-patterns)

---

### Encryption and Caching

**What happens:** Use encryption for sensitive data and generic caching for improved performance.

```python
from miso_client import MisoClient, load_config

client = MisoClient(load_config())
await client.initialize()

# Encryption (requires ENCRYPTION_KEY in .env)
encrypted = client.encrypt('sensitive-data')
decrypted = client.decrypt(encrypted)
print('Decrypted:', decrypted)

# Generic caching (automatically uses Redis if available, falls back to memory)
await client.cache_set('user:123', {'name': 'John', 'age': 30}, 600)  # 10 minutes TTL
user = await client.cache_get('user:123')
if user:
    print('Cached user:', user)
```

**Configuration:**

```bash
# Add to .env
ENCRYPTION_KEY=your-32-byte-encryption-key
```

→ [API Reference](docs/api-reference.md#encryption-methods)  
→ [Cache Methods](docs/api-reference.md#cache-methods)

---

### Testing with API Key

**What happens:** When `API_KEY` is set in your `.env` file, you can authenticate requests using the API key as a bearer token, bypassing OAuth2 authentication. This is useful for testing without setting up Keycloak.

```python
from miso_client import MisoClient, load_config

client = MisoClient(load_config())
await client.initialize()

# Use API_KEY as bearer token (for testing only)
api_key_token = "your-api-key-from-env"
is_valid = await client.validate_token(api_key_token)
# Returns True if token matches API_KEY from .env

user = await client.get_user(api_key_token)
# Returns None (API key auth doesn't provide user info)
```

**Configuration:**

```bash
# Add to .env for testing
API_KEY=your-test-api-key-here
```

**Important:** 
- API_KEY authentication bypasses OAuth2 validation completely
- User information methods (`get_user()`, `get_user_info()`) return `None` when using API_KEY
- Token validation returns `True` if the bearer token matches the configured `API_KEY`
- This feature is intended for testing and development only

---

## 🔧 Configuration

```python
from miso_client import MisoClientConfig, RedisConfig

config = MisoClientConfig(
    controller_url="http://localhost:3000",  # Required: Controller URL
    client_id="ctrl-dev-my-app",              # Required: Client ID
    client_secret="your-secret",              # Required: Client secret
    redis=RedisConfig(                        # Optional: For caching
        host="localhost",
        port=6379,
    ),
    log_level="info",                         # Optional: 'debug' | 'info' | 'warn' | 'error'
    api_key="your-test-api-key",              # Optional: API key for testing (bypasses OAuth2)
    cache={                                   # Optional: Cache TTL settings
        "role_ttl": 900,       # Role cache TTL (default: 900s)
        "permission_ttl": 900, # Permission cache TTL (default: 900s)
    }
)
```

**Recommended:** Use `load_config()` to load from `.env` file automatically.

→ [Complete Configuration Reference](docs/configuration.md)

---

## 📚 Documentation

- **[Getting Started](docs/getting-started.md)** - Detailed setup guide
- **[API Reference](docs/api-reference.md)** - Complete API documentation
- **[Configuration](docs/configuration.md)** - Configuration options
- **[Examples](docs/examples.md)** - Framework-specific examples
- **[Troubleshooting](docs/troubleshooting.md)** - Common issues and solutions

---

## 🏗️ Architecture

The SDK consists of five core services:

- **AuthService** - Token validation and user authentication
- **RoleService** - Role management with Redis caching
- **PermissionService** - Fine-grained permissions
- **LoggerService** - Centralized logging with API key authentication
- **RedisService** - Caching and queue management (optional)

→ [Architecture Details](docs/api-reference.md#architecture)

---

## 🌐 Setup Your Application

**First time setup?** Use the AI Fabrix Builder:

1. **Create your app:**
   ```bash
   aifabrix create myapp --port 3000 --database --language python
   ```

2. **Login to controller:**
   ```bash
   aifabrix login
   ```

3. **Register your application:**
   ```bash
   aifabrix app register myapp --environment dev
   ```

4. **Start development** and then deploy to Docker or Azure.

→ [Full Quick Start Guide](https://github.com/esystemsdev/aifabrix-builder/blob/main/docs/QUICK-START.md)

---

## 💡 Next Steps

### Learn More
- [FastAPI Integration](docs/examples.md#fastapi-integration) - Protect API routes
- [Django Middleware](docs/examples.md#django-middleware) - Django integration
- [Flask Decorators](docs/examples.md#flask-decorators) - Decorator-based auth
- [Error Handling](docs/examples.md#error-handling) - Best practices

### Common Tasks

**Add authentication middleware (FastAPI):**
```python
from fastapi import Depends, HTTPException, Security
from fastapi.security import HTTPBearer
from miso_client import MisoClient

security = HTTPBearer()
client = MisoClient(load_config())

async def get_current_user(credentials = Security(security)):
    token = credentials.credentials
    is_valid = await client.validate_token(token)
    if not is_valid:
        raise HTTPException(status_code=401, detail="Invalid token")
    return await client.get_user(token)
```

**Protect routes by role (FastAPI):**
```python
@app.get('/admin')
async def admin_panel(user = Depends(get_current_user), credentials = Security(security)):
    token = credentials.credentials
    is_admin = await client.has_role(token, 'admin')
    if not is_admin:
        raise HTTPException(status_code=403, detail="Forbidden")
    
    # Admin only code
    return {"message": "Admin panel"}
```

**Use environment variables:**
```bash
MISO_CLIENTID=ctrl-dev-my-app
MISO_CLIENTSECRET=your-secret
MISO_CONTROLLER_URL=http://localhost:3000
REDIS_HOST=localhost
REDIS_PORT=6379
MISO_LOG_LEVEL=info
API_KEY=your-test-api-key  # Optional: For testing (bypasses OAuth2)
```

---

## 🐛 Troubleshooting

**"Cannot connect to controller"**  
→ Verify `controllerUrl` is correct and accessible  
→ Check network connectivity

**"Redis connection failed"**  
→ SDK falls back to controller-only mode (slower but works)  
→ Fix: `aifabrix up` to start Redis

**"Client token fetch failed"**  
→ Check `MISO_CLIENTID` and `MISO_CLIENTSECRET` are correct  
→ Verify credentials are configured in controller  
→ Ensure `ENCRYPTION_KEY` environment variable is set (required for encryption service)

**"Token validation fails"**  
→ Ensure Keycloak is running and configured correctly  
→ Verify token is from correct Keycloak instance  
→ Check that `python-dotenv` is installed if using `.env` files

→ [More Help](docs/troubleshooting.md)

---

## 📦 Installation

```bash
# pip
pip install miso-client

# Development mode
pip install -e .

# With dev dependencies
pip install "miso-client[dev]"
```

---

## 🔗 Links

- **GitHub Repository**: [https://github.com/esystemsdev/aifabrix-miso-client-python](https://github.com/esystemsdev/aifabrix-miso-client-python)
- **PyPI Package**: [https://pypi.org/project/miso-client/](https://pypi.org/project/miso-client/)
- **Builder Documentation**: [https://github.com/esystemsdev/aifabrix-builder](https://github.com/esystemsdev/aifabrix-builder)
- **Issues**: [https://github.com/esystemsdev/aifabrix-miso-client-python/issues](https://github.com/esystemsdev/aifabrix-miso-client-python/issues)

---

## 📄 License

This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.

---

**Made with ❤️ by eSystems Nordic Ltd.**
