FOCUSCurrently working on ScheduleSomething and LayerdEvents algorithmsLearn More
FOCUSCurrently working on ScheduleSomething and LayerdEvents algorithmsLearn More
FOCUSCurrently working on ScheduleSomething and LayerdEvents algorithmsLearn More
FOCUSCurrently working on ScheduleSomething and LayerdEvents algorithmsLearn More
ScalingArchitecture
Multi-Tenant Architecture
DocsscalingArchitectureMulti-Tenant Architecture
GitHub Live Sync

Multi-Tenant Architecture

Live technical documentation fetched from GitHub repository omghante/metapilot/docs/architecture/multi-tenancy.md

Multi-Tenancy & Cryptography Architecture

MetaPilot is built from the ground up for multi-tenant isolation, supporting multi-level account hierarchies and cryptographic secret storage.

1. Account Hierarchy Model

Rendering diagram...

2. Tenant Resolution Middleware

Tenant resolution occurs automatically on every request via
tenants.middleware.TenantMiddleware
:
python
class TenantMiddleware:
    """
    Middleware that resolves the active tenant for each request.
    Tenant is resolved from:
    1. X-Tenant-ID HTTP Header (Primary for API calls)
    2. JWT Token 'tenant_id' claim (Secondary for authenticated users)
    3. URL path / Query parameter (Fallback)
    """
Once resolved,
request.tenant
is attached to the request context. ViewSets and QuerySets automatically scope database operations:
python
def get_queryset(self):
    return Tenant.objects.filter(id=self.request.tenant.id)

3. Fernet AES-256 Secret Encryption

Tenant configurations (
TenantConfig
model) store sensitive API credentials, including Meta Access Tokens and Webhook Verify Tokens.

Cryptographic Implementation

Secrets are encrypted at rest using Fernet symmetric encryption (
cryptography.fernet.Fernet
), which uses:
  • AES-256 in CBC mode with a 256-bit key for encryption.
  • HMAC using SHA256 for data authentication and integrity.
python
@staticmethod
def get_fernet():
    key = getattr(settings, 'FERNET_KEY', '')
    if isinstance(key, str):
        key = key.encode()
    try:
        return Fernet(key)
    except (ValueError, TypeError):
        if getattr(settings, 'DEBUG', False):
            # Development fallback key
            return Fernet(b'KHS39TFFYZFLCfUNv1NNbPRZN2C1w7FKYmsl4ZcJ-Ok=')
        raise

Methods:

  • config.set_value(plain_value)
    : Encrypts plaintext string and stores ciphertext in
    encrypted_value
    .
  • config.get_value()
    : Decrypts
    encrypted_value
    and returns plaintext.