-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Hardware-procurement & asset-lifecycle SCM with an AI decision layer — the LLM advises, deterministic code decides, and a 29-scenario safety harness proves it.
SCM-Master joins three things off-the-shelf tools keep apart — procurement (what you buy, from whom), warehouse flow (receiving into a fast-turning transit warehouse), and asset lifecycle (following each serial unit from arrival to disposal) — under one unbroken provenance spine. On top sits a decision layer: an LLM copilot that proposes buys, a should-cost engine that turns a vendor quote into a defensible cost floor, and a TCO/TSCMC rollup that follows each asset's whole-life cost. Every money-moving decision passes a tested deterministic gate; that boundary is itself regression-tested by an agent-safety harness that feeds the gate hostile AI advice and proves it holds.
It runs live as two isolated stacks — a self-seeding public demo and a forge-locked production stack — each with its own analytics cockpit.
Stack: Python 3.12 · FastAPI · SQLAlchemy 2.0 (typed) · Alembic · Pydantic 2 · Postgres 16 / SQLite · Anthropic Claude (claude-sonnet-4-6, advisory) · Nixtla statsforecast · LightGBM + SHAP (shadow) · Docker · Railway · GitHub Actions (6-job CI)
- What it is
- The three problems it solves
- The decision layer — AI on a short leash
- Key decisions
- API surface
- Quality & trust
- Live deployment
Deep-dive pages: Architecture · Workflows · Security-Model · Data-Model · Design-Decisions · Setup-and-Deployment
| Domain | Hardware procurement for a datacenter: a small transit warehouse feeds equipment into racks. |
| Operational spine | Procurement → receiving → asset lifecycle, with an unbroken provenance link from each serial unit back to its PO line. |
| Decision layer | LLM copilot (advisory) + should-cost engine + TCO/TSCMC rollup — all deterministic where money is concerned. |
| Governing rule | The LLM advises, deterministic code decides. The model proposes; supplier, quantity, price, cost floor, and the place/stage/escalate disposition are all computed by tested code. |
| Standout | A 29-scenario agent-safety harness that runs the real gate against hostile AI advice and proves it refuses or clamps every time. See Security-Model. |
| Status | Working MVP / capstone deliverable. Phases 0–10 done; Phase 6 (SAP + Coupa write-back) in progress. |
| Problem | Why ERPs handle it badly | How SCM-Master answers it |
|---|---|---|
| The supplier is a moving target (long, spiky chip lead times; re-source mid-flight). | Most systems tie a purchase to a supplier and lose the thread on a switch. |
Product (the spec) and ProductSupplier (one source's price/MOQ/lead-time) are separate. Re-sourcing a line is a one-field repoint — identity, history, and in-flight orders survive. |
| "What should this cost?" has no answer in the quote. | No independent number to push back with. | The should-cost engine rebuilds the config from its BOM — commodity-indexed materials + benchmarked silicon — and produces a defensible cost floor and target price. The gap to the quote is the addressable saving. |
| Purchase price is a fraction of real cost. | A GPU node's lifetime OpEx can exceed what you paid. | The TCO layer follows each asset's whole-life cost and rolls it up to the SCOR/APQC TSCMC ratio. |
| Concern | Who decides | AI involved? |
|---|---|---|
| What to buy / how much / from whom | Deterministic — net demand + MOQ + inventory-position model; supplier from sourcing service | No, never |
| Demand forecast (the order's basis) | Deterministic — Syntetos–Boylan routing → run-rate / TSB, or statsforecast (Croston/SBA). Pure CPU stats |
No — zero LLM tokens |
| Confidence score (gates auto-place) | Deterministic — agent/confidence.py from the buy's evidence, factor-by-factor |
No — the LLM's self-reported confidence is recorded but never gates |
| Auto-place vs. escalate | Deterministic gate — confidence ≥ 0.90 and order < €200k, else a human | No |
| Cost floor (should-cost) / TCO | Deterministic — commodity-indexed teardown + whole-life rollup | No |
| Plain-language rationale / narration | The LLM writes the human-readable "why" over already-computed numbers | Advisory only — if wrong or absent, the decision is unchanged |
| Grounded operational Q&A | The LLM answers over a live read-only snapshot | Read-only, never writes |
Single LLM entry point: agent/client.py::call_claude. The key is optional — with no ANTHROPIC_API_KEY the agent runs deterministically (templated narration), boots fast, and costs zero tokens. See Workflows and Design-Decisions.
| Decision | What was chosen | Why |
|---|---|---|
| Who decides spend | Deterministic gate, never the LLM | Money decisions must be tested, auditable, CFO-defensible |
| Confidence score | Computed from evidence, not LLM-asserted | A model hallucinating 0.99 must not trigger a buy |
| Auto-place threshold |
confidence ≥ 0.90 AND order < €200k, else a human |
A bounded, legible rule |
| Forecast engine |
statsforecast (Croston/SBA) for intermittent SKUs, flag-gated |
Benchmarked vs hand-rolled TSB: ~24% lower error at 1000 SKUs, at zero LLM tokens |
| ML / deep learning | Evaluated, deferred (not omitted) | No outcome data yet; trees beat nets on tabular procurement; a black box fails the audit. The ML seam is built (LightGBM shadow mode) |
| Concurrency & scale | Row-locked write guards, pooled DB, indexed hot paths | A guard that fails under concurrency isn't deterministic |
All under /api/v1; OpenAPI at /docs. Most writes are JWT + role-gated.
| Group | Representative endpoints |
|---|---|
| Auth |
POST /auth/login, /auth/register (admin), /auth/me
|
| Catalog |
/organizations, /products, /product-suppliers
|
| Procurement |
/purchase-orders, /{id}/status, /{id}/items/{lineId}/resource (supplier swap) |
| Flow / receiving |
/locations, POST /purchase-orders/{id}/receipts (units → assets) |
| Assets |
/assets, /{id}/transition, /move, /events, /provenance
|
| Planning |
/planning/inbound, /capacity, /forecast, /inventory, /capacity-flow, /capacity/diagnosis
|
| Requisitions |
POST /requisitions/run, /manual, /packages, PATCH …/lines/{id}, …/approve, …/reject, /calibration
|
| Agent (advisory) |
POST /agent/sourcing-recommendation, GET /agent/insights, POST /agent/ask, POST /agent/purchasing-run (+/confirm) |
| Should-cost |
POST /products/{id}/should-cost, GET …/cost-gap, …/sensitivity, analytics/should-cost/{by-supplier,savings}
|
| TCO |
GET /assets/{id}/tco, /tco/portfolio, /tco/by-class
|
| Integrations |
POST /integrations/coupa/import (idempotent, dry_run) |
| Analytics exports |
/analytics/exports/{forecast-accuracy,demand-history,spend}.csv, /analytics/spend[...]
|
| Signal | Detail |
|---|---|
| Agent-safety harness | 29 scenarios (8 correctness + 10 weekly-run adversarial + 11 requisition) — see Security-Model |
| Test suite | 52 test files, 333 passing; CI-gated ≥80% coverage floor |
| CI | 6 jobs: ruff + migrate-check + pytest/coverage · Postgres smoke · bandit (SAST) · pip-audit (CVEs) · agent-eval |
| Production hardening | Fail-closed config guard, per-IP login rate limit, row-locked write guards, indexed hot paths |
Two isolated stacks sharing no database. Demo self-seeds a lived-in Frankfurt-DC operation on every boot; production (SCM_ENV=prod) is forge-locked — never seeds, no demo accounts, Postgres-only, fails closed on a weak SECRET_KEY. See Setup-and-Deployment.
| Page | What's inside |
|---|---|
| Architecture | Layered structure, request lifecycle, module map, hexagonal integration boundary |
| Workflows | The five engines/pipelines: purchasing gate, should-cost, TCO, forecasting, calibration |
| Security-Model | The 29-scenario agent-safety harness, auth/RBAC, forge-lock, hardening |
| Data-Model | Every domain model, enums, state machines, the provenance spine |
| Design-Decisions | The defensible choices: who decides spend, forecast engine, ML deferral, concurrency |
| Setup-and-Deployment | Local run, Docker, the two-stack Railway deployment, env vars |
SCM-Master — Hardware procurement & asset-lifecycle SCM with an AI decision layer · Repository · Built by Eugen Müller
Overview
Deep dives