Skip to content

Architecture

SaaSGuard follows Domain-Driven Design (DDD) with a hexagonal (ports & adapters) structure. The domain layer has zero infrastructure dependencies.

Domain Contexts

graph TB
    subgraph customer_domain["Customer Domain"]
        CE[Customer Entity]
        CV[PlanTier, MRR Value Objects]
        CR[CustomerRepository Interface]
    end

    subgraph usage_domain["Usage Domain"]
        UE[UsageEvent Entity]
        UV[FeatureAdoptionScore Value Object]
        UR[UsageRepository Interface]
    end

    subgraph prediction_domain["Prediction Domain"]
        CM[ChurnModelService]
        RM[RiskModelService]
        PE[PredictionResult Entity]
        PV[ChurnProbability, RiskScore Value Objects]
    end

    subgraph gtm_domain["GTM Domain"]
        OE[Opportunity Entity]
        GV[SalesStage Value Object]
        GR[OpportunityRepository Interface]
    end

    subgraph ai_summary_domain["AI Summary Domain"]
        SP[SummaryPort ABC]
        GS[GuardrailsService]
        ESE[ExecutiveSummary Entity]
        SC[SummaryContext]
    end

    subgraph application["Application Layer"]
        PCS[PredictChurnUseCase]
        CRS[ComputeRiskScoreUseCase]
        GESC[GenerateExecutiveSummaryUseCase]
        AQU[AskCustomerQuestionUseCase]
        GC360[GetCustomer360UseCase]
    end

    subgraph infrastructure["Infrastructure Layer"]
        DB[(DuckDB)]
        DBT[dbt Models\nmart_churn_features\nmart_risk_scores]
        API[FastAPI\n/predictions\n/summaries]
        ML[Model Registry .pkl]
        LLM[LLM Adapters\nGroq / Ollama]
        SUP[Apache Superset\n4 Dashboards]
    end

    GC360 --> PCS
    GC360 --> CE
    GC360 --> DB
    PCS --> CM
    PCS --> CE
    CRS --> RM
    GESC --> PCS
    GESC --> CE
    GESC --> SP
    GESC --> GS
    AQU --> PCS
    AQU --> SP

    CM --> PE
    RM --> PE
    SP --> LLM
    GS --> ESE
    SC --> CE
    SC --> PE

    CR --> DB
    UR --> DB
    GR --> DB
    DB --> DBT
    DBT --> SUP
    API --> PCS
    API --> CRS
    API --> GESC
    API --> AQU
    ML --> CM
    ML --> RM

Request Flow

sequenceDiagram
    participant Client
    participant FastAPI as FastAPI (app/)
    participant UseCase as PredictChurnUseCase
    participant Domain as ChurnModelService
    participant Repo as CustomerRepository
    participant DB as DuckDB

    Client->>FastAPI: POST /predictions/churn {customer_id}
    FastAPI->>UseCase: execute(customer_id)
    UseCase->>Repo: get_by_id(customer_id)
    Repo->>DB: SELECT * FROM customers WHERE ...
    DB-->>Repo: CustomerRecord
    Repo-->>UseCase: Customer entity
    UseCase->>Domain: predict(customer)
    Domain-->>UseCase: PredictionResult
    UseCase-->>FastAPI: PredictionResult
    FastAPI-->>Client: 200 {churn_probability, risk_score, shap_values}

AI Summary Request Flow

sequenceDiagram
    participant Client
    participant FastAPI as FastAPI (app/)
    participant UC as GenerateExecutiveSummaryUseCase
    participant Predict as PredictChurnUseCase
    participant LLM as SummaryPort (Groq/Ollama)
    participant Guard as GuardrailsService
    participant DB as DuckDB

    Client->>FastAPI: POST /summaries/customer {customer_id, audience}
    FastAPI->>UC: execute(customer_id, audience)
    UC->>DB: get_by_id(customer_id)
    UC->>Predict: execute(customer_id)
    Predict-->>UC: PredictionResult + SHAP features
    UC->>DB: fetch events, tickets, GTM context
    UC->>LLM: generate(SummaryContext, audience)
    LLM-->>UC: raw narrative
    UC->>Guard: validate(raw_text, context)
    Guard-->>UC: (final_text + watermark, GuardrailResult)
    UC-->>FastAPI: ExecutiveSummary entity
    FastAPI-->>Client: 200 {summary, churn_probability, confidence_score, guardrail_flags}

Folder → Layer Mapping

Folder DDD Layer Rule
src/domain/ Domain No imports from infra or app. Pure Python.
src/application/ Application Orchestrates domain objects. No DB calls.
src/infrastructure/ Infrastructure Implements repository interfaces. DB/ML/HTTP.
app/ Delivery (API) Thin layer. Calls application services only.
dbt_project/ Infrastructure SQL transformations over DuckDB.