# Balinyaar — Server (ASP.NET Core, Clean Architecture)

Backend API for the Balinyaar application. It is an **ASP.NET Core (.NET 10)** solution organized around **Clean Architecture**, with:

- **CQRS** via `martinothamar/Mediator` (source-generated; not MediatR)
- **ASP.NET Core Identity** with **JWE** (signed + encrypted JWT) and **OTP** authentication
- **Dynamic, permission-based authorization**
- **EF Core** persistence (SQL Server) with the Repository + Unit of Work patterns
- A modular **gRPC plugin** mounted via Application Parts
- Observability out of the box: Serilog, OpenTelemetry, Prometheus metrics, health checks

> Looking for an architecture/file map to navigate the code? See [CLAUDE.md](CLAUDE.md) (agent guide)
> and [CONVENTIONS.md](CONVENTIONS.md) (coding rules).

## Requirements

- [.NET 10 SDK](https://dotnet.microsoft.com/)
- SQL Server (local instance, or the containerized one from `docker-compose.yml`)

## Running locally

From the `server/` folder:

```bash
dotnet restore Baya.sln
dotnet build Baya.sln
dotnet run --project src/API/Baya.Web.Api/Baya.Web.Api.csproj
```

By default the API listens on **https://localhost:5002** and serves Swagger UI at **/swagger**.

On startup the app **applies EF Core migrations** and **seeds default users** automatically, so a reachable database (see `appsettings.json` → `ConnectionStrings`) is required.

### Configuration

Settings live in `src/API/Baya.Web.Api/appsettings.json` (+ `appsettings.Development.json`):

- `ConnectionStrings:SqlServer` — main application database
- `ConnectionStrings:logDb` — Serilog SQL sink database
- `IdentitySettings` — `SecretKey` (signing), `Encryptkey` (AES-128 encryption, exactly 16 chars), `Issuer`, `Audience`, token lifetimes

## Running with Docker

Generate a development HTTPS certificate (used by the container):

```bash
dotnet dev-certs https -ep $env:USERPROFILE/.aspnet/https/baya.pfx -p Strong@Password
dotnet dev-certs https --trust
```

Build and start the API together with SQL Server 2022:

```bash
docker build -t bobby-baya -f Dockerfile .
docker-compose up -d
```

The compose stack exposes the API on `http://localhost:5000` / `https://localhost:5001` and SQL Server on `localhost:1435`.

## Solution layout

```
src/
├── Core/
│   ├── Baya.Domain          Entities + domain primitives (the core / "brain")
│   └── Baya.Application      CQRS features, contracts (interfaces), MediatR pipeline
├── Infrastructure/
│   ├── Baya.Infrastructure.Persistence    EF Core DbContext, configs, repositories, UoW, migrations
│   ├── Baya.Infrastructure.Identity        Identity, JWE/JWT, OTP, dynamic permissions
│   ├── Baya.Infrastructure.CrossCutting    Cross-cutting concerns (logging)
│   └── Baya.Infrastructure.Monitoring      Health checks, OpenTelemetry, Prometheus
├── API/
│   ├── Baya.Web.Api          Presentation: REST controllers, Program.cs (startup)
│   ├── Baya.WebFramework     Reusable web config: base controller, filters, middleware, Swagger
│   └── Plugins/Baya.Web.Plugins.Grpc   Self-contained gRPC plugin
├── Shared/
│   └── Baya.SharedKernel     Shared extensions/helpers referenced by every layer
└── Tests/                        xUnit test setup + Identity tests
```

## The layers (why they exist)

### Domain

The core of the project. Each entity may carry its own behavior. Entities derive from a common `BaseEntity`, which lets the persistence layer discover models via reflection to register them and drive migrations.

### Application

Routes requests and defines the **contracts** (interfaces) the system depends on, without knowing their implementations. This is where **CQRS** lives: Commands and Queries are kept separate and dispatched to their handlers by **Mediator** (`martinothamar/Mediator`, source-generated). Cross-cutting concerns (validation, metrics) are applied as Mediator pipeline behaviors.

### Infrastructure

Implements the contracts the Application layer declares — the parts needed to run in the real world:

- **Persistence** — the chosen database (SQL Server via EF Core). Repositories give self-describing, persistence-agnostic data access; Unit of Work keeps multi-step writes atomic and consistent.
- **Identity** — registration, authentication and authorization using ASP.NET Core Identity, with JWE tokens, OTP login, and a dynamic access-control system.
- **CrossCutting** — services used across the whole app, such as logging.
- **Monitoring** — health checks, distributed tracing/metrics, and Prometheus.

### WebFramework

Keeps `Program.cs` thin by moving each piece of configuration into its own reusable class (filters, middleware, Swagger, API versioning, the base controller, etc.).

### Web.Api

The presentation layer — an ASP.NET Core Web API exposing versioned REST controllers under `Controllers/V1`.

### Web.Plugins.Grpc

A standalone module that adds gRPC endpoints to the same host via **Application Parts**, giving modularity (the "plugin" middle ground between a monolith and microservices) without a separate deployment. It registers its services and pipeline through extension methods called from `Program.cs`.

## Tests

```bash
dotnet test Baya.sln
```

Each layer is designed to be testable in isolation; `Baya.Tests.Setup` provides the shared test scaffolding.

## License

See [LICENSE.md](LICENSE.md).
