# ADAS Core Backend API

> **ADAS Core** — Backend platform developed by **Epigram Technologies**.  
> Implements **Clean Architecture** with a **Modular Monolith** pattern, built on **.NET 8** and designed for scalability, maintainability, and flexible deployment in industrial and institutional environments.

---

## Table of Contents

1. [Overview](#overview)
2. [Architecture](#architecture)
3. [Solution Structure](#solution-structure)
4. [Functional Modules](#functional-modules)
5. [Getting Started](#getting-started)
6. [Configuration](#configuration)
7. [Authentication](#authentication)
8. [Logging](#logging)
9. [Testing](#testing)
10. [Technologies & Dependencies](#technologies--dependencies)
11. [Conventions & Best Practices](#conventions--best-practices)

---

## Overview

ADAS Core is the main backend API for the ADAS platform. It follows a modular monolith architecture where business domains are organized into independent modules while sharing a common infrastructure and application core.

Key characteristics:

- **Clean Architecture**: Clear separation between Domain, Application, Infrastructure, and Presentation layers.
- **Modular Monolith**: Business modules are self-contained and can be extracted into microservices if needed.
- **Pluggable Authentication**: Supports multiple authentication strategies via a common abstraction layer.
- **Structured Logging**: Full observability through Serilog with multiple sinks and enrichers.
- **Production Ready**: Multi-configuration builds, Docker support, Prometheus metrics, and comprehensive test coverage.

---

## Architecture

The architecture follows the principles of **Clean Architecture** (Onion Architecture), ensuring that business rules remain independent of frameworks, UI, and infrastructure concerns.

### Design Principles

| Principle | Description |
|-----------|-------------|
| **Dependency Rule** | Dependencies always point inward. The Domain layer has zero external dependencies. |
| **Separation of Concerns** | Each layer has a single responsibility (Domain, Application, Infrastructure, Authentication, Modules). |
| **Framework Independence** | The Domain layer contains pure business logic without references to ASP.NET Core, databases, or external libraries. |
| **Testability** | Business rules can be unit-tested in isolation without infrastructure concerns. |
| **Modularity** | Functional domains are encapsulated in independent modules with minimal shared surface. |

### Layer Responsibilities

| Layer | Projects | Responsibility |
|-------|----------|--------------|
| **Domain** | `adas-core.Domain` | Entities, value objects, domain events, business rules, and repository interfaces. |
| **Application** | `adas-core.Application` | Use cases, application services, DTOs, and orchestration logic. |
| **Infrastructure** | `adas-core.Infrastructure` | Persistence, messaging, caching, external APIs, and technical concerns. |
| **Authentication** | `adas-core.Authentication` | Authentication abstractions, JWT handling, and security middleware. |
| **Presentation** | `adas-core` (Host) | ASP.NET Core Web API, controllers, dependency injection composition, and module registration. |
| **Modules** | `adas-core.module.*` | Independent business domains with their own entities, services, and controllers. |

### Architecture Diagram

```mermaid
flowchart TB
    subgraph Presentation["Presentation Layer"]
        H[adas-core Host<br/>ASP.NET Core Web API]
    end

    subgraph Auth["Authentication Layer"]
        A[adas-core.Authentication<br/>JWT / Middleware / Abstractions]
        L[adas-core.LdapLogin]
        Lo[adas-core.LocalLogin]
    end

    subgraph Application["Application Layer"]
        AP[adas-core.Application<br/>Use Cases / Services / DTOs]
    end

    subgraph Domain["Domain Layer"]
        D[adas-core.Domain<br/>Entities / Rules / Interfaces]
    end

    subgraph Infrastructure["Infrastructure Layer"]
        I[adas-core.Infrastructure<br/>Persistence / Messaging / Cache]
    end

    subgraph Modules["Business Modules"]
        M1[module.LightBeacons]
        M2[module.ProxyDevices]
        M3[module.Relays]
    end

    H --> A
    H --> AP
    AP --> D
    A --> AP
    A --> D
    L --> A
    Lo --> A
    Lo --> I
    I --> AP
    I --> M1
    I --> M3
    M1 --> D
    M2 --> D
    M3 --> D
```

### Request Flow Example

```mermaid
sequenceDiagram
    participant Client
    participant Host as adas-core (Host)
    participant Auth as Authentication
    participant App as Application
    participant Mod as Module
    participant Inf as Infrastructure
    participant DB as Database

    Client->>Host: HTTP Request
    Host->>Auth: Validate JWT / Authenticate
    Auth-->>Host: ClaimsPrincipal
    Host->>App: Invoke Use Case
    App->>Mod: Execute Business Logic
    Mod->>Inf: Persist / Query
    Inf->>DB: Database Operation
    DB-->>Inf: Result
    Inf-->>Mod: Data
    Mod-->>App: Domain Result
    App-->>Host: DTO / Response
    Host-->>Client: HTTP Response
```

> **Note on Dependencies**: The `Infrastructure` project references the `Application` and specific modules it supports. Modules reference `Domain` (preferentially) or `Application` for shared abstractions. The Host references all layers and wires them together via the dependency injection container.

---

## Solution Structure

```
adas-core/
├── adas-core.sln                    # Main solution file
├── Dockerfile                        # Multi-stage Linux image
├── .dockerignore                     # Docker build exclusions
├── .gitignore / .gitattributes       # Version control
│
├── adas-core/                        # API Host (ASP.NET Core Web)
│   ├── Program.cs                    # Application bootstrap
│   ├── appsettings.json              # Base configuration
│   ├── appsettings.Local.json        # Local overrides
│   └── Properties/
│       └── launchSettings.json       # Launch profiles
│
├── adas-core.Domain/                 # Pure Domain layer
│   ├── Entities/
│   ├── ValueObjects/
│   ├── Interfaces/                   # Repository contracts
│   └── Events/                       # Domain events
│
├── adas-core.Application/            # Use Case layer
│   ├── Services/                     # Application services
│   ├── DTOs/                         # Data transfer objects
│   └── Interfaces/                   # Service contracts
│
├── adas-core.Infrastructure/         # Technical Infrastructure
│   ├── Persistence/                  # Data access implementations
│   ├── Messaging/                    # RabbitMQ / EasyNetQ wrappers
│   └── Cache/                        # Redis abstractions
│
├── adas-core.Authentication/         # Security abstractions
│   ├── TokenService.cs               # JWT generation / validation
│   └── Middleware/                   # Auth middleware
│
├── adas-core.LdapLogin/             # LDAP / Active Directory strategy
│   └── LdapAuthenticationService.cs
│
├── adas-core.LocalLogin/            # Local database strategy
│   └── LocalAuthenticationService.cs
│
├── adas-core.module.LightBeacons/   # Functional module: Light Beacons
│
├── adas-core.module.ProxyDevices/   # Functional module: Proxy Devices
│
├── adas-core.module.Relays/         # Functional module: Relays
│
└── adas-core.Test/                  # Automated test suite (NUnit)
```

### Cross-Project Reference Rules

```
adas-core.Host         → references → Domain, Application, Infrastructure, Authentication, Modules
adas-core.Application  → references → Domain
adas-core.Infrastructure → references → Application, Modules
adas-core.Authentication → references → Application, Domain
adas-core.LdapLogin    → references → Authentication
adas-core.LocalLogin   → references → Authentication, Infrastructure
Modules                → references → Domain (preferentially)
adas-core.Test         → references → Domain, Infrastructure, Host
```

---

## Functional Modules

Each module is an autonomous functional domain encapsulating its own business logic, entities, and services.

| Module | Project | Description |
|--------|---------|-------------|
| **LightBeacons** | `adas-core.module.LightBeacons` | Management and control of light beacons: state, lighting patterns, visual alerts, and synchronization. |
| **ProxyDevices** | `adas-core.module.ProxyDevices` | Administration of intermediary devices: registration, heartbeat, remote configuration, and telemetry. |
| **Relays** | `adas-core.module.Relays` | Control of electromechanical/electronic relays: ON/OFF commands, time scheduling, and real-time status. |

> Modules communicate with each other preferentially through **domain events** published via `EasyNetQ` (RabbitMQ). This ensures loose coupling and allows future extraction into independent microservices.

### Module Interaction Diagram

```mermaid
flowchart LR
    subgraph Core["Application Core"]
        A[Application Layer]
        D[Domain Layer]
        I[Infrastructure Layer]
    end

    subgraph Modules["Business Modules"]
        M1[LightBeacons]
        M2[ProxyDevices]
        M3[Relays]
    end

    subgraph Bus["Message Bus"]
        R[(RabbitMQ\nvia EasyNetQ)]
    end

    M1 -->|reads/writes| I
    M2 -->|reads/writes| I
    M3 -->|reads/writes| I
    M1 -->|depends on| D
    M2 -->|depends on| D
    M3 -->|depends on| D
    M1 -.->|publishes events| R
    M2 -.->|publishes events| R
    M3 -.->|publishes events| R
    R -.->|consumes events| M1
    R -.->|consumes events| M2
    R -.->|consumes events| M3
```

---

## Getting Started

### Prerequisites

| Requirement | Min. Version | Verification |
|-------------|--------------|--------------|
| [.NET SDK](https://dotnet.microsoft.com/download) | **8.0.x** | `dotnet --version` |
| [Docker](https://docs.docker.com/get-docker/) *(optional)* | 24.x+ | `docker --version` |
| MongoDB *(if not using Docker)* | 6.0+ | `mongod --version` |
| Redis *(if not using Docker)* | 7.0+ | `redis-cli --version` |
| RabbitMQ *(optional, for messaging)* | 3.12+ | `rabbitmqctl status` |

### Quick Start

```bash
# 1. Clone the repository
git clone <repository-url>
cd adas-core

# 2. Restore dependencies
dotnet restore adas-core.sln

# 3. Build the solution
dotnet build adas-core.sln --configuration Release

# 4. Run the API in development mode
cd adas-core
dotnet run --launch-profile "Development"
```

The API will be available by default at:
- **HTTP**: `http://localhost:5000`
- **HTTPS**: `https://localhost:5001`

*(Ports are configurable in `Properties/launchSettings.json`.)*

### Docker Deployment

```bash
# Build the image
docker build -t adas-core:latest .

# Run the container
docker run -p 8080:80 \
  -e ASPNETCORE_ENVIRONMENT=Production \
  adas-core:latest
```

> The `Dockerfile` uses a multi-stage Linux-based build optimized for production deployment.

### Build Configurations

The solution supports multiple build configurations for different environments:

| Configuration | Purpose |
|---------------|---------|
| `Debug` | Local development with full debug symbols. |
| `DebugNoMedia` | Debug without embedded media resources (faster compilation). |
| `Release` | Optimized build for general production. |
| `ReleaseNoMedia` | Release without media resources (smaller artifact). |
| `H12O-Release` | Release profile for the **H12O** product line. |
| `HRYC-Release` | Release profile for the **HRYC** product line. |
| `SmacsServer` | Release profile for the **SMACS** server environment. |

```bash
# Example: build a specific profile
dotnet build adas-core.sln --configuration H12O-Release
```

> All `Release` and `H*-Release` configurations enforce `TreatWarningsAsErrors`, ensuring production-quality code.

---

## Configuration

### appsettings.json

The application uses the standard ASP.NET Core configuration hierarchy:

```json
{
  "ConnectionStrings": {
    "MongoDb": "mongodb://localhost:27017/adas-core",
    "Redis": "localhost:6379"
  },
  "Authentication": {
    "Scheme": "Local",
    "Jwt": {
      "Secret": "your-secret-key-min-32-characters-long",
      "Issuer": "ADAS-Core",
      "Audience": "ADAS-Clients",
      "ExpirationMinutes": 60
    }
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Information",
      "Override": {
        "Microsoft": "Warning",
        "System": "Warning"
      }
    }
  }
}
```

### Environment Variables

| Variable | Purpose | Example |
|----------|---------|---------|
| `ASPNETCORE_ENVIRONMENT` | Runtime environment | `Development`, `Staging`, `Production` |
| `ASPNETCORE_URLS` | Binding URLs | `http://+:80;https://+:443` |
| `ConnectionStrings__MongoDb` | MongoDB connection string | `mongodb://...` |
| `Authentication__Jwt__Secret` | JWT signing key | *(use secrets manager in production)* |

### User Secrets

In development, store sensitive values using the .NET User Secrets manager:

```bash
cd adas-core
dotnet user-secrets set "Authentication:Jwt:Secret" "your-dev-secret-key"
```

---

## Authentication

The system implements a **multi-strategy authentication** model using a provider pattern. The host application registers the appropriate strategy at runtime based on configuration.

### Available Strategies

| Strategy | Project | Description |
|----------|---------|-------------|
| **LDAP / Active Directory** | `adas-core.LdapLogin` | Corporate authentication against LDAP directories. Uses `Novell.Directory.Ldap.NETStandard`. |
| **Local Database** | `adas-core.LocalLogin` | Internal authentication with users stored in MongoDB. Passwords hashed with **BCrypt**. |

### Architecture

```mermaid
flowchart LR
    subgraph AuthLayer["Authentication Abstraction"]
        A[adas-core.Authentication\nJWT / Claims / Middleware]
    end

    subgraph Strategies["Concrete Strategies"]
        L[adas-core.LdapLogin]
        Lo[adas-core.LocalLogin]
    end

    subgraph Stores["Identity Stores"]
        LDAP[(LDAP / AD Server)]
        DB[(MongoDB)]
    end

    Client -->|HTTP Request| A
    A -->|resolve strategy| L
    A -->|resolve strategy| Lo
    L -->|bind| LDAP
    Lo -->|query| DB
```

### Configuration Example

```json
{
  "Authentication": {
    "Scheme": "Local",
    "Jwt": {
      "Secret": "<32-char-secret-key-here>",
      "Issuer": "ADAS-Core",
      "Audience": "ADAS-Clients",
      "ExpirationMinutes": 60
    },
    "Ldap": {
      "Server": "ldap.corp.local",
      "Port": 636,
      "UseSSL": true,
      "BindDN": "CN=service,OU=Users,DC=corp,DC=local"
    }
  }
}
```

To switch strategies, change the `Authentication:Scheme` value to `"Ldap"` or `"Local"`.

---

## Logging

The application uses **Serilog** for structured logging, integrated natively with ASP.NET Core.

### Features

- **Structured JSON output** for machine parsing and aggregation.
- **Automatic enrichment** with thread identifiers, exception details, and dynamic context properties.
- **Multiple sinks**: Console for containers, rolling files for persistence.
- **Compact format** for efficient storage and transmission.

### Configured Sinks

| Sink | Output | Format |
|------|--------|--------|
| **Console** | Standard output / Docker logs | Compact JSON |
| **File** | `./Logs/log-.txt` (daily rotation) | Compact JSON |

### Enrichers

| Enricher | Source | Purpose |
|----------|--------|---------|
| `ThreadId` | `Serilog.Enrichers.Thread` | Track request thread correlation. |
| `ExceptionDetails` | `Serilog.Exceptions` | Capture full exception object graphs. |
| `DynamicProperties` | `Serilog.Enrichers.Dynamic` | Add runtime context properties. |

### Prometheus Metrics

The `/metrics` endpoint exposes application and runtime metrics in Prometheus-compatible format:

```bash
curl http://localhost:5000/metrics
```

---

## Testing

The `adas-core.Test` project provides comprehensive test coverage using **NUnit** as the test framework.

### Running Tests

```bash
# Full test suite
dotnet test adas-core.sln

# With code coverage
dotnet test adas-core.sln --collect:"XPlat Code Coverage"

# Verbose output
dotnet test adas-core.sln --logger "console;verbosity=detailed"
```

### Test Types

| Type | Description | Tools |
|------|-------------|-------|
| **Unit** | Isolated tests of domain rules and application services. | NUnit, Moq |
| **Integration** | End-to-end tests with embedded MongoDB (`Mongo2Go`). | NUnit, Mongo2Go |
| **Fakes** | Isolated tests of external dependencies using assembly shims. | Microsoft Fakes |

### Code Quality Gates

- `TreatWarningsAsErrors = True` (Debug / Release)
- Nullable reference types enabled across all projects
- NUnit static analysis via `NUnit.Analyzers`
- Coverlet code coverage collection

---

## Technologies & Dependencies

### Framework & Runtime

| Technology | Version |
|------------|---------|
| .NET / ASP.NET Core | **8.0** |
| C# Language | **12** |

### Key Libraries

| Category | Package | Version | Purpose |
|----------|---------|---------|---------|
| **ORM** | `Microsoft.EntityFrameworkCore` | 8.0.27 | Relational data access |
| **NoSQL** | `MongoDB.Driver` / `MongoDB.Bson` | 3.9.0 | MongoDB access and serialization |
| **Migrations** | `MongoMigrations.Core` | 4.0.15 | MongoDB schema migrations |
| **Cache** | `StackExchange.Redis` | 2.13.17 | Distributed caching |
| **Messaging** | `EasyNetQ` | 8.1.4 | RabbitMQ async messaging |
| **Push** | `WebPush` | 1.0.13 | Browser push notifications |
| **Auth** | `Microsoft.AspNetCore.Authentication.JwtBearer` | 8.0.8 | JWT Bearer authentication |
| **Auth** | `System.IdentityModel.Tokens.Jwt` | 8.18.0 | JWT token handling |
| **Security** | `BCrypt.Net-Next` | 4.2.0 | Password hashing |
| **Security** | `Novell.Directory.Ldap.NETStandard` | 4.0.0 | LDAP integration |
| **Validation** | `FluentValidation` | 12.1.1 | Input validation rules |
| **Mapping** | `AutoMapper` | 16.1.1 | Entity <-> DTO mapping |
| **Scheduling** | `Quartz` | 3.18.1 | Background job scheduling |
| **Scripts** | `Microsoft.CodeAnalysis.CSharp.Scripting` | 5.3.0 | Dynamic C# evaluation |
| **Logging** | `Serilog` + sinks + enrichers | 4.x | Structured logging pipeline |
| **Metrics** | `prometheus-net.AspNetCore` | 8.2.1 | Prometheus metrics endpoint |
| **Testing** | `NUnit` / `NUnit3TestAdapter` | 4.6.1 / 6.2.0 | Unit testing framework |
| **Testing** | `Moq` | 4.20.72 | Dependency mocking |
| **Testing** | `Mongo2Go` | 4.1.0 | Embedded MongoDB for tests |
| **Testing** | `coverlet.collector` | 10.0.1 | Code coverage |

---

## Conventions & Best Practices

### Code Style

1. **Naming**: `PascalCase` for types, methods, and properties; `camelCase` for parameters and locals.
2. **Namespaces**: Must match the physical file path (e.g., `adas_core.Domain.Entities`).
3. **Nullables**: Explicit nullable reference types are enforced (`nullable enable`).
4. **Interfaces**: Prefixed with `I` (e.g., `IRepository<T>`, `ITokenService`).
5. **Async**: Asynchronous method names must end with `Async` suffix.
6. **XML Docs**: All public APIs must include XML documentation comments.

### Dependency Direction

- The **Domain** layer must never reference any other project.
- **Application** depends only on **Domain**.
- **Infrastructure** depends on **Application** and modules it supports.
- **Authentication** depends on **Application** and **Domain**.
- Concrete login strategies depend on **Authentication**.
- **Modules** depend on **Domain** (preferentially) or **Application** for shared abstractions.
- **Tests** reference the layers under test; use mocking for external dependencies.

### Commit Messages

Use descriptive English commit messages following conventional commits:

```
feat(beacon): add color pattern validation
fix(auth): resolve JWT expiration drift
refactor(infra): extract Redis connection factory
docs(readme): update build instructions
```

### Scalability Notes

- **Modules** are designed to be extracted as independent microservices with minimal changes.
- **Domain events** enable asynchronous inter-module communication without tight coupling.
- **Message bus** (RabbitMQ via EasyNetQ) supports horizontal scaling of consumers.
- **Redis** caching layer reduces database load for frequently accessed data.
- **Prometheus metrics** allow monitoring and alerting in container orchestration environments.

---

## License

Copyright (c) **Epigram Technologies** — All rights reserved.

This software is proprietary and confidential. Reproduction, distribution, or modification without express written authorization from Epigram Technologies is prohibited.

---

<p align="center">
  <strong>ADAS Core v2.1</strong> &nbsp;|&nbsp; Built with .NET 8
</p>
