Refactor code structure for int in alll ids instesd defult using long

This commit is contained in:
2026-07-15 15:35:54 +05:30
parent 6c7f53350f
commit ed2ee87c68
120 changed files with 2775 additions and 12494 deletions
+3 -3
View File
@@ -58,7 +58,7 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
> **Status: COMPLETE.** Audit trail, doc numbering, reason codes, JournalEntryStub, negative-stock block, and now **authentication** (external AuthHex IdP integration) are all done + verified. The §6 security gate (NFR-03 auth + AR-01 audit) is met — **§1–§5 flipped `[~]`→`[x]`** (2026-07-14). FEFO pick-ordering is the only intentional deferral.
- [x] Audit log on every mutation (who/when/old→new) — `AuditLog` (jsonb `changeSet`), written by an `ErpDbContext.SaveChanges` override (`AuditScribe`): Create captures the field set, Update captures **only changed fields as {old,new}**, Delete captures the prior row; PK/RowVersion excluded; ledger/layer/seq/self/journal excluded. Actor from `ICurrentUser` (system=1 until auth). Read via `GET /audit-logs`. **Verified** (Item create+update old→new; StockAdjustment create). This is the **AR-01 compensating control** (02-SECURITY B.3) — app-level append-only; DB-role UPDATE/DELETE revoke still deferred.
- [x] Document numbering sequences (per type, per year) — `NumberSequence` + `NumberSequenceService` (atomic `INSERT … ON CONFLICT … RETURNING` inside the doc's UoW txn; gap-controlled). Verified issuing + incrementing PR/RFQ/PO.
- [x] Auth: **external AuthHex IdP integration** (2026-07-14) — ERPCore is a resource server. `JwtAuthExtensions` validates **RS256** against AuthHex's RSA **public** key (config `Auth:RsaPublicKeyXml``RsaSecurityKey`; `MapInboundClaims=false`), issuer `AuthHex`, audience `AuthHexClient` (no JWKS → static key). `[Authorize(ErpAccess)]` on `ApiControllerBase` gates every v1 endpoint; the `ErpAccess` policy `RequireAuthenticatedUser` + optional `RequireClaim(UserTypeCode/RoleCode)` from `Auth:RequiredUserTypeCode`/`RequiredRoleCode` (empty ⇒ any valid ERP token — AuthHex is ERP-dedicated). **Shadow-user JIT provisioning:** `ShadowUserClaimsTransformation` (`IClaimsTransformation`) maps the token's `UserId` **GUID** → a local `users` row (`auth_user_id` unique; Username/DisplayName = `NIC`), idempotent, and injects the local `long` id as `nameid` so `ICurrentUser.AuditUserId` resolves the real actor. Migration `AddAuthUserId`. **Verified:** no token→401; `/health`,`/api/meta`,Swagger anonymous; valid token→200; shadow user provisioned (User 2, Username=NIC, AuthUserId=GUID); item Create **audited as the shadow user (id 2, not system)**; re-request reuses the same user; door gate → **403** on UserType mismatch, **200** on match.
- [x] Auth: **external AuthHex IdP integration** (2026-07-14) — ERPCore is a resource server. `JwtAuthExtensions` validates **RS256** against AuthHex's RSA **public** key (config `Auth:RsaPublicKeyXml``RsaSecurityKey`; `MapInboundClaims=false`), issuer `AuthHex`, audience `AuthHexClient` (no JWKS → static key). `[Authorize(ErpAccess)]` on `ApiControllerBase` gates every v1 endpoint; the `ErpAccess` policy `RequireAuthenticatedUser` + optional `RequireClaim(UserTypeCode/RoleCode)` from `Auth:RequiredUserTypeCode`/`RequiredRoleCode` (empty ⇒ any valid ERP token — AuthHex is ERP-dedicated). **Shadow-user JIT provisioning:** `ShadowUserClaimsTransformation` (`IClaimsTransformation`) maps the token's `UserId` **GUID** → a local `users` row (`auth_user_id` unique; Username/DisplayName = `NIC`), idempotent, and injects the local `int` id as `nameid` so `ICurrentUser.AuditUserId` resolves the real actor. Migration `AddAuthUserId`. **Verified:** no token→401; `/health`,`/api/meta`,Swagger anonymous; valid token→200; shadow user provisioned (User 2, Username=NIC, AuthUserId=GUID); item Create **audited as the shadow user (id 2, not system)**; re-request reuses the same user; door gate → **403** on UserType mismatch, **200** on match.
- [x] JournalEntryStub emitted per stock movement (data only) — `JournalEntryStub` written in `FifoCostingService.PostLedgerAsync` for every ledger entry (In → Dr Inventory `1300` / Cr Clearing `2100`; Out reverses; amount = movement value). Placeholder accounts until a chart of accounts exists. Read via `GET /journal-entries`. **Verified** (GRN In 700, ADJ Out 70).
- [x] Negative-stock policy enforcement (default block) — enforced in `FifoCostingService.ConsumeAsync``409 STOCK_NEGATIVE_BLOCKED` (verified). Per-item override still a config stub.
- [~] FEFO picking for perishables; block expired / on-hold issue — **issue-block done + verified** (`ONHOLD_NOT_ISSUABLE`, `EXPIRED_BATCH_BLOCKED`; on-hold/expired layers excluded from consume). FEFO *pick ordering* (oldest-expiry first) not yet built.
@@ -123,13 +123,13 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
### 2026-07-14 — Auth architecture change: external AuthHex IdP (docs-only pass)
- **Plan changed:** auth is no longer a local `POST /auth/login` inside ERPCore. A **separate AuthHex IdP** (runs on `:5011`, source at `c:\Users\WAS\Documents\Developments\ERP_Auth_Service\`) owns login/registration/recovery; ERPCore becomes a **resource server** that only validates AuthHex tokens. Updated `docs/10-BACKEND-PHASE1.md` (header, A.4 auth/audit-actor, A.5 DI, B.2.3, FR-X-01, NFR-03, C.7 `USER`, C.9, B.8.4 decision #10) and this file. **No code changed this pass.**
- **Decisions (confirmed):** (1) identity = **shadow-user JIT provisioning** — add `auth_user_id` GUID (unique) to `users`, keep all `long` FKs; (2) authorization = **door-gate to an ERP `UserType`/`Role`**, per-endpoint RBAC still deferred; (3) scope = **docs only** now, code integration is a follow-up.
- **Decisions (confirmed):** (1) identity = **shadow-user JIT provisioning** — add `auth_user_id` GUID (unique) to `users`, keep all `int` FKs; (2) authorization = **door-gate to an ERP `UserType`/`Role`**, per-endpoint RBAC still deferred; (3) scope = **docs only** now, code integration is a follow-up.
- **Confirmed AuthHex facts:** RS256 (RSA 2048; ERPCore needs the static **public** key — no JWKS), issuer `AuthHex`, audience `AuthHexClient`, lifetime 1000 min prod / 60 min dev; claims `UserId`(GUID)/`UserTypeCode`/`RoleCode`/`NIC`/`jti`/`iat` (no `sub`/`nameid`); BCrypt password hashing; login `POST /api/loginUser {identifier,password}`.
- **Open blockers (resolve before the code phase):** exact ERP `UserTypeCode`/`RoleCode` for the door gate (must exist in AuthHex); RSA public-key distribution + rotation process (no JWKS); shadow-user `Username`/`DisplayName` source (token has no name); secrets hygiene in AuthHex config (private key/SMTP/DB in plaintext); `docs/11 §2.0` still documents `/auth/login` (now AuthHex-owned) — recommend a follow-up annotation.
### 2026-07-14 (2) — Auth code integration: AuthHex resource server (§6 COMPLETE → §1–§5 flipped `[x]`)
- **RS256 validation:** `JwtAuthExtensions` rewritten — `RsaSecurityKey` from `Auth:RsaPublicKeyXml` (AuthHex public key), `ValidIssuer=AuthHex`, `ValidAudience=AuthHexClient`, `ValidAlgorithms=[RS256]`, `MapInboundClaims=false` (keeps `UserId`/`UserTypeCode`/`RoleCode` verbatim). `appsettings.json` `Jwt``Auth` (public key + issuer/audience + `RequiredUserTypeCode`/`RequiredRoleCode`); removed the HS256 dev signing key.
- **Door policy** `ErpAccess`: `RequireAuthenticatedUser` + optional `RequireClaim(UserTypeCode/RoleCode)` when configured (AuthHex is ERP-dedicated → empty default = any valid token). `[Authorize(ErpAccess)]` on `ApiControllerBase`; `MetaController`/health/Swagger stay anonymous.
- **Shadow-user provisioning:** `ShadowUserClaimsTransformation` (`IClaimsTransformation`, scoped) maps token `UserId` GUID → local `users` row (`auth_user_id` unique, Username/DisplayName=`NIC`), idempotent w/ race-safe re-read, injects local `long` id as `nameid`. `User.AuthUserId` (Guid?) + `AuthHexClaims` consts + migration `AddAuthUserId`.
- **Shadow-user provisioning:** `ShadowUserClaimsTransformation` (`IClaimsTransformation`, scoped) maps token `UserId` GUID → local `users` row (`auth_user_id` unique, Username/DisplayName=`NIC`), idempotent w/ race-safe re-read, injects local `int` id as `nameid`. `User.AuthUserId` (Guid?) + `AuthHexClaims` consts + migration `AddAuthUserId`.
- **Verified (minted AuthHex-shaped RS256 token, signed with AuthHex's real private key):** no token→401; `/health`,`/api/meta`,Swagger→200 anon; valid token→200; POST item→201 **audited as shadow user id 2** (Username=NIC, AuthUserId=GUID), not system; repeat request reuses user (1 provision); door gate `RequiredUserTypeCode=WAREHOUSE` → ERP-type token **403**, WAREHOUSE-type token **200**. Build clean; migration applied.
- **§6 COMPLETE.** Only intentional deferral left in Phase 1: FEFO pick-ordering (§6, `[~]`). Follow-ups: set the real ERP `Auth:RequiredUserTypeCode`/`RoleCode` for production; secure the RSA key rotation process.