# 00 · CORE — ERP System (Phase 1: Inventory & Supply Chain) > **This file is the hub. Start every task here.** > It defines the repository structure, the tech stack, how to stand up a runnable backend, and — most importantly — **where to go next** for any piece of work. Do not begin backend or frontend work without first reading the relevant section below and following the routing table in §7. --- ## 1. What this project is A modular ERP built in phases. **Phase 1** delivers the **Inventory & Supply Chain** subsystem: master data, procurement, goods receipt, and stock management (FIFO costing, multi-warehouse, single-tenant). | Decision | Value | |---|---| | Costing method | **FIFO** (cost-layer tracking, per item per warehouse) | | Warehouses | **Multi-warehouse** | | Tenancy | **Single-tenant** | | Approvals (PO, adjustment) | **Auto-approve**, config-gated off (RBAC deferred) | | Access control | Authentication only; **RBAC deferred**, user identity stamped for audit | | Vendor invoice / 3-way match | **Deferred** to Accounting phase (GRN retains hooks) | Full requirements live in the backend spec (see §7). This file does **not** duplicate them. **Phase 2 (HRM)** is now underway alongside Phase 1 — see §7 routing to `12-BACKEND-HRM.md` / `13-BACKEND-HRM-API.md` / `21-FRONTEND-HRM.md`. Sales has its own API reference at `14-BACKEND-SALES-API.md`. --- ## 2. Repository structure ``` erp-monorepo/ ├── README.md # Root: what this is + how to run both sides ├── .gitignore # ignore appsettings.*.json secrets, .env*, bin/, obj/, node_modules/ │ ├── Backend/ # ASP.NET Core Web API (.NET 10) — see §5 to initialize │ ├── ERPCore.sln │ ├── PROGRESS.md # ← backend change checklist (Claude-maintained, git-shared) │ └── ERPCore/ # single Web API project (folders, not multi-project) │ ├── Frontend/ # Next.js (App Router + TypeScript) — already initialized │ └── PROGRESS.md # ← frontend change checklist (Claude-maintained, git-shared) │ └── docs/ # ALL documentation ├── 00-CORE.md # ← you are here (hub) ├── 01-DOC-GUIDE.md # documentation map + tracking conventions ├── 02-SECURITY.md # accepted-risks register + per-feature security checklist ├── 10-BACKEND-PHASE1.md # backend spec: SRS + ER/entities + tech + architecture ├── 11-BACKEND-PHASE1.md # backend API reference (complete req/res) ├── 14-BACKEND-SALES-API.md # sales API reference (invoices, slips, free issues, reports) ├── 12-GENERAL-LEDGER-INTEGRATION.md # ERPCore ↔ external General Ledger service (transport only) ├── 20-FRONTEND.md # frontend user-flows + architecture rules + validation posture └── 21-GENERAL-LEDGER-FRONTEND.md # Ledgers section: reports UI + cash/bank accounts ``` The `Backend/ERPCore/` internal layout is created in §5.3. --- ## 3. Tech stack ### Backend | Concern | Choice | |---|---| | Runtime | **.NET 10** (`net10.0`) | | Framework | ASP.NET Core Web API (controllers) | | ORM | EF Core 10 | | Database | **PostgreSQL** (Npgsql provider) | | Auth | JWT bearer (simple in-app login; RBAC deferred) | | Logging | Serilog (file sink) | | API docs | Swashbuckle / Swagger UI | | Health | HealthChecks + EF Core DB check → `GET /health` | ### Frontend | Concern | Choice | |---|---| | Framework | **Next.js** (App Router) + TypeScript | | State/forms | **Plain React hooks** (`useState` / custom hooks) | | Validation | **Dependency-free** (hand-rolled) — client-side for UX only; **server is authoritative** | | API access | Typed fetch client against the backend (`NEXT_PUBLIC_API_BASE_URL`) | > The Frontend project is **already initialized**. Do not scaffold it here. For all frontend architecture, flows, and validation rules, go to `20-FRONTEND.md`. ### Database PostgreSQL, running on **localhost** for development. Secrets management (User Secrets / environment variables) is deferred; see §5.4 for the current local configuration and the note on secrets. --- ## 4. Architecture (high-level, both sides) ### Backend layering — strict, one direction ``` Controller → Service → Repository → UnitOfWork/DbContext (DTOs) (logic) (entities) (transaction boundary) ``` Rules (non-negotiable for Phase 1): - **DTOs at the controller boundary.** Controllers accept and return DTOs only — **never** EF entities and **never** `DbContext`. - **Services hold business logic** and return DTOs. Controllers stay thin (HTTP concerns only). - **Repositories own EF entities** and data access. No business rules in repositories. - **UnitOfWork is the transaction boundary.** Every stock-affecting operation (GRN confirm, transfer dispatch/receive, adjustment, return, count post) runs inside a single UoW transaction. - **FIFO lives in a domain service** (`FifoCostingService`), invoked by stock services inside the UoW transaction — **not** in a controller or repository. Layer consumption must lock affected rows for concurrency safety. - **Errors use RFC 7807 `ProblemDetails`** (ASP.NET Core default). Domain errors carry a stable `code`. The error catalog is in `11-BACKEND-PHASE1.md`. - **Audit actor** is derived from the authenticated principal (token `sub`), never from the request body. ### Frontend (summary — full rules in `20-FRONTEND.md`) - Stick to the existing initialized architecture; do not restructure. - **Validate on the client for UX, but never trust it.** The server re-validates everything. Business rules that depend on server state (stock availability, negative-stock block, over-receipt tolerance, FIFO sufficiency) are **server-authoritative** and must not be assumed valid client-side. --- ## 5. Backend initialization (runnable) Follow in order. Commands assume repo root `erp-monorepo/`. ### 5.1 Prerequisites - **.NET 10 SDK** (`dotnet --version` → `10.0.x`) - **PostgreSQL** running on localhost, and a login you can use - **EF Core CLI**: `dotnet tool install --global dotnet-ef` (or `dotnet tool update --global dotnet-ef`) - Node.js (for the Frontend, handled separately) ### 5.2 Create solution and project ```bash mkdir -p Backend && cd Backend dotnet new sln -n ERPCore dotnet new webapi -n ERPCore --use-controllers -f net10.0 dotnet sln add ERPCore/ERPCore.csproj cd ERPCore ``` ### 5.3 Create the internal folder structure ```bash # from Backend/ERPCore/ mkdir -p Controllers Services/Interfaces Services/Stock \ Repositories/Interfaces \ Domain/Entities Domain/Enums \ Dtos/Common \ Common/Models \ Infra/UoW Infra/Persistence/Configurations Infra/Persistence/Migrations Infra/Auth Infra/Logging \ System/Errors \ HealthChecks ``` Target internal layout: ``` ERPCore/ ├── ERPCore.csproj ├── Program.cs ├── appsettings.json # base (no real secrets) ├── appsettings.Development.json # local dev (localhost Postgres) ├── appsettings.Production.json # env-var driven ├── Controllers/ # HTTP; DTOs in/out ├── Services/ # business logic → DTOs │ ├── Interfaces/ │ └── Stock/ (StockService, FifoCostingService) ├── Repositories/ # EF data access (entities) │ └── Interfaces/ ├── Domain/ │ ├── Entities/ # 38 EF entities │ └── Enums/ # ItemType, TrackingMode, HoldStatus, Direction, *Status ├── Dtos/ # request/response DTOs (+ Common: paging) ├── Common/Models/ # PagedResult, PaginationMeta, Result ├── Infra/ │ ├── UoW/ # IUnitOfWork, UnitOfWork │ ├── Persistence/ # ErpDbContext, Configurations/, Migrations/ │ ├── Auth/ # JWT setup, ICurrentUser (audit source) │ └── Logging/ # Serilog config ├── System/Errors/ # domain exceptions, error codes, ProblemDetails middleware └── HealthChecks/ # EF Core DB health check ``` ### 5.4 Add packages Pinned versions below are current for .NET 10 at time of writing. All `Microsoft.EntityFrameworkCore.*` packages **must share the same version**. ```bash # from Backend/ERPCore/ dotnet add package Microsoft.EntityFrameworkCore --version 10.0.9 dotnet add package Microsoft.EntityFrameworkCore.Design --version 10.0.9 dotnet add package Microsoft.EntityFrameworkCore.Tools --version 10.0.9 dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 10.0.2 dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 10.0.9 dotnet add package Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore --version 10.0.9 dotnet add package Serilog.AspNetCore --version 9.0.0 dotnet add package Serilog.Sinks.File --version 6.0.0 dotnet add package Swashbuckle.AspNetCore --version 10.2.3 ``` Resulting `ERPCore.csproj`: ```xml net10.0 enable enable all runtime; build; native; contentfiles; analyzers; buildtransitive all runtime; build; native; contentfiles; analyzers; buildtransitive ``` > **Swashbuckle v10 note:** v10 upgraded to `Microsoft.OpenApi` 2.x and emits **OpenAPI 3.1**. `Program.cs` uses `using Microsoft.OpenApi;` and `AddSwaggerGen(...)` / `UseSwagger()` / `UseSwaggerUI()`. ### 5.5 App settings (three files) `appsettings.json` (base — no real secrets; placeholder only): ```json { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "ConnectionStrings": { "DefaultConnection": "Host=localhost;Port=5432;Database=ERPCore;Username=CHANGE_ME;Password=CHANGE_ME" }, "Jwt": { "Issuer": "ERPCore", "Audience": "ERPCore.Clients", "SigningKey": "CHANGE_ME_DEV_ONLY_32+_CHARS", "AccessTokenMinutes": 120 }, "AllowedHosts": "*" } ``` `appsettings.Development.json` (local dev — used by `dotnet run` in Development): ```json { "ConnectionStrings": { "DefaultConnection": "Host=localhost;Port=5432;Database=ERPCore;Username=postgres;Password=postgres" }, "Jwt": { "SigningKey": "dev-only-signing-key-please-change-me-0123456789" } } ``` `appsettings.Production.json` (values injected from environment variables at deploy time): ```json { "ConnectionStrings": { "DefaultConnection": "" }, "Jwt": { "SigningKey": "" } } ``` > **Secrets note (current phase):** we are on **localhost dev only**, so the Development file holds local credentials for convenience. Before any shared/staging/production use, move secrets to **User Secrets** (dev) and **environment variables** (prod), keep `appsettings.Development.json` / `appsettings.Production.json` out of git (see root `.gitignore`), and rotate any credential that was ever committed. ### 5.6 Minimal `Program.cs` wiring (outline) ```csharp using Microsoft.EntityFrameworkCore; using Microsoft.OpenApi; using Serilog; var builder = WebApplication.CreateBuilder(args); // Serilog (file sink) builder.Host.UseSerilog((ctx, cfg) => cfg .ReadFrom.Configuration(ctx.Configuration) .WriteTo.File("logs/erpcore-.log", rollingInterval: RollingInterval.Day)); builder.Services.AddControllers(); // EF Core + PostgreSQL builder.Services.AddDbContext(o => o.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); // ProblemDetails (RFC 7807) builder.Services.AddProblemDetails(); // JWT bearer auth (RBAC deferred; identity used for audit stamp) builder.Services.AddAuthentication(/* JwtBearer options from config */); builder.Services.AddAuthorization(); // Health checks (EF Core DB) builder.Services.AddHealthChecks().AddDbContextCheck(); // Swagger builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(o => o.SwaggerDoc("v1", new() { Title = "ERPCore API", Version = "v1" })); // DI: register UoW, repositories, services, ICurrentUser, FifoCostingService here var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseExceptionHandler(); // maps to ProblemDetails app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.MapHealthChecks("/health"); app.Run(); ``` ### 5.7 Create the database and run ```bash # ensure the ERPCore database exists in your local Postgres, then: dotnet ef migrations add InitialCreate -o Infra/Persistence/Migrations dotnet ef database update dotnet run ``` **Verify:** - Swagger UI at `https://localhost:/swagger` - Health at `https://localhost:/health` → `Healthy` Entity/DbContext modeling (the 42 entities, configurations, enums) is specified in `10-BACKEND-PHASE1.md`. Do not invent the schema here — follow that file. --- ## 6. Running the frontend The Frontend is already initialized. Point it at the backend: ```bash cd Frontend cp .env.local.example .env.local # set NEXT_PUBLIC_API_BASE_URL=https://localhost: npm install npm run dev ``` All frontend work is governed by `20-FRONTEND.md`. --- ## 7. Routing — where to go next **Every task starts here, then jumps to the right doc.** Do not work from memory; open the target doc. | If you are working on… | Go to | |---|---| | Requirements, business rules, entities, ER model, data types, architecture detail (Phase 1: Inventory & Supply Chain) | **`10-BACKEND-PHASE1.md`** | | API endpoints, request/response shapes, error catalog, enums (Phase 1) | **`11-BACKEND-PHASE1.md`** | | HRM requirements, business rules, entities, ER model (Phase 2) | **`12-BACKEND-HRM.md`** | | HRM API endpoints, request/response shapes, error catalog (Phase 2) | **`13-BACKEND-HRM-API.md`** | | Connecting to the external General Ledger service (proxy, config, API key) | **`12-GENERAL-LEDGER-INTEGRATION.md`** | | The Ledgers frontend section (reports, cash/bank accounts) | **`21-GENERAL-LEDGER-FRONTEND.md`** | | Sales API endpoints, request/response shapes, error catalog, enums | **`14-BACKEND-SALES-API.md`** | | Frontend user-flows, screen flow, architecture rules, validation posture (Phase 1) | **`20-FRONTEND.md`** | | HRM frontend user-flows (Phase 2) | **`21-FRONTEND-HRM.md`** | | Manufacturing requirements, business rules, entities, stock/costing integration, API (Phase 2) | **`30-BACKEND-PHASE2.md`** | | Manufacturing frontend user-flows — template canvas, run board, run execution (Phase 2) | **`21-FRONTEND-PHASE2.md`** | | Security risks per feature, accepted-risk register, pre-ship checklist | **`02-SECURITY.md`** | | Understanding the doc system, reading order, tracking conventions | **`01-DOC-GUIDE.md`** | | Recording backend changes made | **`Backend/PROGRESS.md`** | | Recording frontend changes made | **`Frontend/PROGRESS.md`** | Quick resolver: - *"Where is the model / an entity defined?"* → `10-BACKEND-PHASE1.md` (Phase 1) / `12-BACKEND-HRM.md` (HRM) — schema is authoritative there. - *"What does this endpoint accept/return?"* → `11-BACKEND-PHASE1.md` (Phase 1) / `13-BACKEND-HRM-API.md` (HRM). - *"What does the sales API accept/return?"* → `14-BACKEND-SALES-API.md`. - *"How should the UI flow / what do I validate where?"* → `20-FRONTEND.md` (Phase 1) / `21-FRONTEND-HRM.md` (HRM). - *"What security risks / checks apply to this feature?"* → `02-SECURITY.md`. --- ## 8. Progress tracking (mandatory) Two checklists track what has actually been built, and travel with code via git: - **`Backend/PROGRESS.md`** — backend changes - **`Frontend/PROGRESS.md`** — frontend changes These are **Claude-maintained**: whenever a change is made on either side, the corresponding `PROGRESS.md` must be updated (tick items, add entries). The format and rules for these files are defined in **`01-DOC-GUIDE.md` §Tracking**. Both files must exist before feature work begins. > **Security gate:** before ticking any data-mutating feature `[x]`, run its checklist in **`02-SECURITY.md`** (Part C) plus the foundational controls (Part B). Accepted Phase-1 exposures are recorded in `02-SECURITY.md` Part A — do not "fix" them ad-hoc. --- ## 9. Documentation maintenance rule There is **one source of truth** per topic. The SRS and API content live **inside** the docs above (not in separate scattered files). When a requirement or endpoint changes, edit it **in place** in `10-`/`11-BACKEND-PHASE1.md` — do not fork copies. See `01-DOC-GUIDE.md` for the full maintenance and navigation rules. --- *End of 00-CORE.md — the hub. Next: `01-DOC-GUIDE.md`.*