Every feature in UpdaterAgent follows a set of shared conventions that keep the codebase predictable across 55+ modules. Understanding these patterns before writing your first line of code will save you from common pitfalls and ensure your changes pass code review without friction.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ShohjahonSohibov/repo-for-agent/llms.txt
Use this file to discover all available pages before exploring further.
Service structure
Each feature module insrc/UpdaterAgent.Application/ follows a strict 4-file layout. This separates the public API surface from internal helpers and keeps large services manageable through partial classes.
Contracts/ use record types for immutability and value-based equality.
Result pattern
Services never throw exceptions for expected business failures. Instead, every service method returnsTask<Result<T>> or Task<Result>, defined in Domain/Abstractions/Result.cs.
.IsSuccess before reading .Data. Reserve exceptions for truly exceptional cases such as unrecoverable infrastructure failures.
Error definitions
Define errors as static members of a dedicated error class for each feature. This makes error codes discoverable and prevents magic strings.Entity conventions
All domain entities must follow these rules consistently to work correctly with EF Core global query filters and the multi-tenant isolation system.- Inherit
AuditableModelBase<long>(addsId,IsDeleted,CreatedAt,UpdatedAt,CreatedBy,UpdatedBy) - Implement
ITenantEntitywith aTenantIdproperty - Add
[Index(nameof(TenantId))]at the class level - Use
[Column("snake_case")]on every property to match PostgreSQL naming
Driver ID convention (LR-1053)
This is the most common source of data integrity bugs. Driver identity is split across two fields with entirely different purposes.| Field | Type | Purpose |
|---|---|---|
Driver.Id | long | Local database primary key — use for all internal operations |
Driver.ImportId | string | External TMS GUID — use only for import and sync with QuickManage |
Stop.AssignedDriverIds stores Driver.Id.ToString(), not ImportId. When reading assigned drivers from a stop, parse back to long and look up by Driver.Id.
Background job conventions
All Hangfire jobs must carry these two attributes and be registered inJobsRegistrar.cs:
[DisableConcurrentExecution(300)]— prevents overlapping runs across distributed instances[AutomaticRetry(Attempts = 0)]— disables automatic retry; failures are logged and alerted via Telegram- Always set tenant context via
ITenantContextServicebefore any database query
Dependency injection
Application services are registered insrc/UpdaterAgent.Application/Dependencies.cs inside ConfigureApplicationServices(). Infrastructure services go in the equivalent Dependencies.cs under UpdaterAgent.Infrastructure.
Scoped unless there is a specific reason for a different lifetime (e.g., IDeviationCalculator is a singleton because it is stateless and expensive to initialize).
API controller conventions
Every controller inControllers/v1/ follows the same attribute pattern:
[Authorize]— every endpoint requires a valid JWT unless explicitly exempted[ApiController]— enables automatic model validation and binding[Route("api/v1/[controller]")]— all routes are versioned underv1[HasPermission(...)]— permission-based authorization usingEnumPermission
Branching and workflow
| Rule | Value |
|---|---|
| Base branch | dev |
| Feature branch | feature/PROJ-123-short-description |
| Bug fix branch | fix/PROJ-123-short-description |
| PR target | dev |
Never merge your own PR unless you have been explicitly authorized to do so. All PRs require at least one technical reviewer approval before merging.