corteq 0.1.0

Enterprise-grade multi-tenant SaaS framework for Rust with security-first design
Documentation
//! # Corteq - Enterprise Multi-Tenant SaaS Framework
//!
//! Corteq is a security-first, multi-tenant SaaS framework for Rust that provides:
//! - **Tenant Data Isolation**: Row-level security (RLS) with compile-time safety
//! - **JWT Authentication**: Tenant context embedded in authentication tokens
//! - **RBAC Authorization**: Tenant-scoped role-based access control
//! - **Audit Logging**: Comprehensive, immutable audit trails
//! - **Encryption**: AES-256-GCM at rest, TLS 1.3 in transit
//! - **Compliance Ready**: GDPR, HIPAA, SOC 2 patterns built-in
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use corteq::CorteqApp;
//! use actix_web::{web, App, HttpServer};
//!
//! #[actix_web::main]
//! async fn main() -> std::io::Result<()> {
//!     let app_config = CorteqApp::builder()
//!         .with_database("postgres://localhost/mydb")
//!         .with_jwt_secret("your-secret-key")
//!         .build()
//!         .await
//!         .expect("Failed to build app");
//!
//!     HttpServer::new(move || {
//!         App::new()
//!             .app_data(web::Data::new(app_config.clone()))
//!     })
//!     .bind("0.0.0.0:3000")?
//!     .run()
//!     .await
//! }
//! ```

#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
#![forbid(unsafe_code)]

pub mod auth;
pub mod cache;
pub mod database;
pub mod domain;
pub mod encryption;
pub mod error;
pub mod middleware;
pub mod repository;

// Re-exports for convenience
pub use auth::{Claims, JwtService};
pub use cache::{MemoryTenantCache, TenantCache};
pub use database::TenantDatabase;
pub use domain::{Tenant, TenantContext};
pub use encryption::{EncryptedData, EncryptionService};
pub use error::{CorteqError, Result};
pub use middleware::{TenantContextMiddleware, TenantExtractor};
pub use repository::TenantRepository;

use sqlx::PgPool;
use std::sync::Arc;

/// Corteq application configuration
#[derive(Clone, Debug)]
pub struct CorteqApp {
    /// Database connection pool
    pub db_pool: PgPool,

    /// JWT service for token validation
    pub jwt_service: JwtService,

    /// Tenant cache for performance
    pub tenant_cache: Arc<dyn TenantCache>,

    /// Tenant repository for database access
    pub tenant_repository: TenantRepository,
}

impl CorteqApp {
    /// Create a new application builder
    pub fn builder() -> CorteqAppBuilder {
        CorteqAppBuilder::default()
    }
}

/// Builder for Corteq applications
#[derive(Default, Debug)]
pub struct CorteqAppBuilder {
    database_url: Option<String>,
    jwt_secret: Option<String>,
    cache: Option<Arc<dyn TenantCache>>,
}

impl CorteqAppBuilder {
    /// Configure database connection
    pub fn with_database(mut self, url: &str) -> Self {
        self.database_url = Some(url.to_string());
        self
    }

    /// Configure JWT secret
    pub fn with_jwt_secret(mut self, secret: &str) -> Self {
        self.jwt_secret = Some(secret.to_string());
        self
    }

    /// Configure custom tenant cache (optional)
    pub fn with_cache(mut self, cache: Arc<dyn TenantCache>) -> Self {
        self.cache = Some(cache);
        self
    }

    /// Build the application configuration
    pub async fn build(self) -> Result<CorteqApp> {
        let database_url = self
            .database_url
            .ok_or_else(|| CorteqError::ConfigError("Database URL is required".to_string()))?;

        let jwt_secret = self
            .jwt_secret
            .ok_or_else(|| CorteqError::ConfigError("JWT secret is required".to_string()))?;

        // Connect to database
        tracing::info!("Connecting to database: {}", database_url);
        let db_pool = PgPool::connect(&database_url)
            .await
            .map_err(CorteqError::DatabaseError)?;

        // Run migrations
        tracing::info!("Running database migrations...");
        sqlx::migrate!("./migrations")
            .run(&db_pool)
            .await
            .map_err(|e| CorteqError::ConfigError(format!("Migration failed: {e}")))?;

        // Initialize JWT service
        let jwt_service = JwtService::new(jwt_secret.as_bytes());

        // Initialize cache (use provided or create default)
        let tenant_cache = self.cache.unwrap_or_else(|| {
            tracing::info!("Using default in-memory tenant cache");
            Arc::new(MemoryTenantCache::default())
        });

        // Create tenant repository
        let tenant_repository = TenantRepository::new(db_pool.clone());

        tracing::info!("✓ Corteq application initialized successfully");

        Ok(CorteqApp {
            db_pool,
            jwt_service,
            tenant_cache,
            tenant_repository,
        })
    }
}