# 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<T>, PaginationMeta, Result<T>
├── 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
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.9" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="10.0.9">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.9" />
    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="10.0.9" />
    <PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
    <PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
  </ItemGroup>

  <ItemGroup>
    <Folder Include="Common\Models\" />
    <Folder Include="Infra\UoW\" />
    <Folder Include="System\Errors\" />
  </ItemGroup>

</Project>
```
> **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<ErpDbContext>(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<ErpDbContext>();

// 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:<port>/swagger`
- Health at `https://localhost:<port>/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:<port>
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`.*
