Files
adas-core/README.md
T
2026-06-26 10:29:23 +02:00

602 lines
20 KiB
Markdown

# 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>