Files
hamid 765cc632d5 backend phase 0: foundation, cross-cutting seams & starter cleanup
Remove the Order demo (entity/feature/repo/config/gRPC/proto) and the three
pre-marketplace migrations; regenerate a fresh InitialBaseline migration.

Stand up the REST surface (PingController + System/Ping CQRS) proving the
Mediator -> behaviors -> OperationResult -> ApiResult envelope end to end.

Close wiring gaps: register LoggingBehavior (outermost) and add the built-in
rate limiter (per-IP global + otp/auth/sensitive policies), placed before
authentication.

Add current-user + audit plumbing: ICurrentUser (HttpContext + null impls),
rename BaseEntity audit fields to CreatedAt/ModifiedAt (DateTimeOffset) +
CreatedById/ModifiedById, stamped by a new AuditFieldInterceptor.

Introduce five cross-cutting seams (IDateTimeProvider, IFieldEncryptor,
ICacheService, IObjectStorage, INotificationDispatcher) with in-memory/local
mocks registered via AddCrossCuttingSeams.

Add Baya.Test.Foundation (encryptor, audit interceptor, ping handler) and
update docs, contracts (swagger.v1.json), handoff, report, and mocks registry.
2026-06-30 22:48:41 +03:30
..
2026-06-16 01:32:43 +03:30
2026-06-16 01:46:53 +03:30
2026-06-21 00:05:07 +03:30
2026-06-16 01:46:53 +03:30
2026-06-16 01:46:53 +03:30
2026-06-16 01:32:43 +03:30
2026-06-21 00:05:07 +03:30

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 (agent guide) and CONVENTIONS.md (coding rules).

Requirements

  • .NET 10 SDK
  • SQL Server (local instance, or the containerized one from docker-compose.yml)

Running locally

From the server/ folder:

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.jsonConnectionStrings) 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
  • IdentitySettingsSecretKey (signing), Encryptkey (AES-128 encryption, exactly 16 chars), Issuer, Audience, token lifetimes

Running with Docker

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

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:

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

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.