Imported from NotHydra/evori-dreamwings-finalis-hackathon-kic (
server/AGENTS.md). Install upstream withnpx skills add NotHydra/evori-dreamwings-finalis-hackathon-kic --skill server. Copyright stays with the author.
AGENTS.md โ server/
Instructions for AI coding agents and contributors working on the backend. Read ../AGENTS.md first for repository-wide rules; this file adds the server-specific contract.
๐ซ NEVER TOUCH GIT OR GITHUB
Agents MUST NOT run any git or GitHub operation โ no commits, no staging, no branches, no pushes, no
ghcommands, no edits to.gitignoreor anything under.git/. Version control is performed exclusively by the human team. The commit history is competition evidence; polluting it is not recoverable. Full rule and rationale:../AGENTS.md ยง0. It outranks every instruction in this file.This applies to scaffolding too: generate the project files, then stop. Do not
git init, do not create an initial commit, and do not let a scaffolding tool do it for you โ pass--skip-git(or the equivalent) to any generator that commits by default.
1. Status
Phase 0 is scaffolded. The NestJS application now has its strict TypeScript/npm toolchain, validated environment configuration, global response envelope, request correlation, structured request logging, exception handling, boundary validation, and health endpoints.
PostgreSQL connectivity, TypeORM migration bootstrap, GET /health/ready, and Docker packaging for Postgres/server/web are implemented. Build the remaining phases on this scaffold.
Phase 1 is complete: migrations create all domain tables, the August/September 2026 hourly_facts partitions, enums, extensions, constraints, and indexes. Phase 1B adds the TypeORM seed entities, preserves all 524 fuel-reference source entries, creates 47 operational canonical unit types, maps only deterministic references, seeds SPO/targets/settings, and creates the environment-backed Argon2id admin account. Empty-database and second-run fingerprint tests verify that the seed is idempotent.
Phase 3 is complete: the canonical unit registry, deterministic normalization, weighted fuzzy matching, configurable thresholds, review queue, merge/create/split/dismiss decisions, profile persistence, replay of quarantined rows, normalized alias conflict protection, and master-data/review API endpoints are implemented.
Phase 4 is complete: Excel/CSV, manual, and contractor FMS doors converge on one transactional ingest pipeline. Raw rows, normalized hourly facts, critical quarantine exceptions, warning findings, review links, duplicate/conflict handling, explicit superseding replacements, FMS idempotency keys, and contractor-scoped token RBAC are implemented with PostgreSQL integration coverage.
Phase 5 is complete: the calculation engine is the sole numeric origin for shared-denominator actual FR, SPO/plan baselines, cycle-time hauling productivity, roll-ups, coverage/provisional state, deterministic lever attribution, and hash-versioned fr_results. The human-authenticated Fuel Ratio, breakdown, and deviation endpoints expose provenance metadata; accepted ingest refreshes roll-ups and recomputes results.
Phase 6 is complete: the analytics layer exposes deterministic daily fuel forecasting, effect-dated emission and cost derivation, dashboard summary, stateless baseline simulation, productivity gap-solving, and fuel-claim reporting. Forecast cache invalidation is input-hash based; all analytical responses expose provenance.
Phase 7 is complete: deterministic insight flags, bounded payloads, Indonesian fallback narration, optional Claude narration with numeric guardrails, payload-hash caching, on-demand rate limiting, batch-summary degradation, insight provenance metadata, and owner-scoped notifications are implemented.
Phase 2 is complete: password/JWT primitives, human session endpoints, capability RBAC, and contractor-scoped API tokens are implemented. Login, atomic refresh rotation, current-device logout, /auth/me, database-current role checks, refresh-token hashing, admin-only token management, deny-by-default capability metadata, FMS route boundary enforcement, and authentication/token audit events have integration coverage.
The design is finished and complete. Do not invent architecture; implement what docs/system-design/ specifies.
2. Stack
| Layer | Choice |
|---|---|
| Framework | NestJS + TypeScript |
| Database | PostgreSQL |
| API | REST, contract-first OpenAPI 3.1, base path /api/v1 |
| Auth | JWT access (15 min) + refresh (7 days); contractor FMS ingest uses scoped API tokens |
| LLM | Claude API, model claude-sonnet-5 โ narrative insight only |
| Packaging | docker-compose โ Postgres + server + web, no cloud dependency |
Full rationale: ../docs/system-design/01-overview-and-architecture.md ยง7.
3. Read these first
Do not read all 14 design documents. Pick by task โ the full table is in ../docs/system-design/00-README.md ยง4.
Bare numbers below refer to documents in ../docs/system-design/; anything else is written as a full path.
| Task | Read in order |
|---|---|
| Scaffold the project | 01 โ 12 |
| Write a migration | 02 โ 03 |
| Implement an endpoint | 02 โ 03 โ 09 โ 11 |
| Implement or change a formula | 02 โ 06 โ docs/02_FUEL_RATIO_CALCULATION.md โ 13 |
| Excel / CSV import | 02 โ 03 โ 04 โ 05 |
| Alias review queue | 02 โ 05 โ 09 |
| Forecast, emission, cost, gap-solver | 02 โ 06 โ 07 |
| LLM insight | 02 โ 06 โ 07 โ 08 |
| Tests | 02 โ 06 โ 13 |
02-domain-model-and-glossary.md is the semantic anchor and holds every numeric constant. Constants are defined there once and referenced everywhere else โ never restate one with a different value.
4. Module layout
server/
โโโ src/
โ โโโ main.ts
โ โโโ app.module.ts
โ โโโ common/ envelope interceptor, exception filters, validation pipes, decorators
โ โโโ auth/ JWT, guards, RBAC
โ โโโ master-data/ contractors, unit types, aliases, profiles
โ โโโ spo/ fuel ranges, availability, productivity
โ โโโ plans/ monthly plans, production targets, fuel prices, settings
โ โโโ ingest/ parsers, pipeline, batches, exceptions
โ โโโ alias/ normalization, matching, review queue, replay
โ โโโ calculation/ FR engine, cycle-time, roll-ups, lever attribution
โ โโโ analytics/ forecasting, emission, cost, simulator, gap-solver
โ โโโ insight/ rule flags, LLM orchestration, cache
โ โโโ audit/ audit events
โ โโโ database/ entities, migrations, seeds
โโโ test/ e2e specs
Dependency rule
MUST NOT create an import cycle. Dependencies flow one way:
analyticsandinsightโcalculationโspo/plans;ingestโaliasโmaster-data.
calculationnever importsingest. Ingest triggers recomputation through an event or an explicit one-directional service call.
5. Hard rules
Each is testable and each has a test case in ../docs/system-design/13-test-specification.md.
5.1 Numbers
- The Supporting/Dewatering denominator is 86,930,000 BCM, read from
production_targets. Never apply a1.05multiplier โ the workbook's version of it is a confirmed mistake. - The calculation engine is the sole origin of numbers.
analytics,insight, and controllers consume its output; they never re-derive a figure. - The LLM never computes. Its payload contains only engine-computed values with units, and every numeric token in its response is validated against that payload. A violation logs
INSIGHT_NUMERIC_VIOLATIONand the deterministic fallback is served instead. - Fuel Ratio for a period is
ฮฃ fuel / ฮฃ productionfor that period โ never the mean of shorter-period ratios. - All four activity components divide by the same
PRODUCTION_TOTAL, so the four sum exactly to the total.
5.2 Data integrity
- No silent failures. A row that cannot be resolved or validated becomes a visible exception attached to its batch. It must never contribute zero quietly.
- A value that could not be computed is
null, never0. - One ingest pipeline. All three doors โ Excel import, manual form, FMS API โ pass through the same normalize โ resolve โ validate โ persist stages. The API door MUST NOT bypass validation.
- Raw payloads are stored verbatim and never modified.
audit_eventsis append-only: the application database role getsINSERTandSELECTonly.- Reference data (SPO, prices, settings) is effect-dated. Changing a value must not rewrite history.
fr_resultsare versioned byinputs_hash; recomputation with unchanged inputs is a no-op, changed inputs create a new version.- Seeds must not invent data. A missing reference value stays missing so ingest raises an exception.
5.3 Version control
No git, no GitHub โ ever. Fully specified in ../AGENTS.md ยง0. Repeated here because scaffolding a NestJS project is exactly the moment a generator or an agent reaches for git init out of habit.
5.4 API
- Every response uses the envelope
{ data, meta, error }. - Analytical responses MUST include
meta.provenanceโ SPO version, plan, denominator, engine version, batch coverage. A figure without provenance cannot be defended in a claim dispute. - Pagination is mandatory on every list endpoint.
POST /ingest/fmsrequires anIdempotency-Keyheader.- Authorisation is enforced server-side on every request; frontend gating is only a usability affordance. Deny by default.
- Contractor API tokens may call
POST /ingest/fmsand nothing else, and only for their own contractor.
6. Golden values
The engine MUST reproduce these from the reference dataset in ../docs/02_FUEL_RATIO_CALCULATION.md, denominator 86,930,000 BCM:
| Quantity | Value |
|---|---|
| Hauler productivity @ 3.9 km | 109.565217 BCM/hr |
| Loading FR | 0.169304 L/BCM |
| Hauling FR | 0.702778 L/BCM |
| Supporting FR | 0.382450 L/BCM |
| Dewatering FR | 0.422150 L/BCM |
| Total FR | 1.676682 L/BCM |
A legacy mode reproducing the workbook's own figures (denominator 91,276,500, Supporting 0.219933, Loading 0.154965) must also exist, so tests can prove the corrections are deliberate rather than accidental.
Test group C in
13-test-specification.mdmust pass 100%. A failing golden value means the system is computing the wrong number and blocks the merge. Coverage floors:calculation/,alias/,ingest/โฅ 90% lines; overall โฅ 75%.
7. Commands and style
Mirror web/ so the repository behaves consistently. Package manager is npm.
cd server
npm install
npm run start:dev # watch mode
npm run build
npm run lint
npm run format
npm run check # prettier --check . && eslint . && tsc -b โ before every commit
npm run test # unit
npm run test:e2e
npm run migration:run
npm run seed # idempotent; SEED_DEMO=true adds the demo dataset
Style follows the repository conventions in ../AGENTS.md ยง6: Prettier with no semicolons, double quotes, 100-column width, 2-space indent, LF; ESLint with type-checked rules and simple-import-sort as an error; TypeScript strict; one-line comments only.
Migrations and seeds are idempotent โ re-running changes nothing.
8. Environment
Secrets have no defaults and are never committed. Full table: ../docs/system-design/12-deployment-and-configuration.md ยง2.
| Required | Optional |
|---|---|
DATABASE_URL |
ANTHROPIC_API_KEY (absent โ rule-flag insight only) |
JWT_ACCESS_SECRET |
LLM_MODEL, LLM_ENABLED, LLM_DAILY_CALL_CAP |
JWT_REFRESH_SECRET |
COVERAGE_FLOOR, PRODUCTION_MISMATCH_TOLERANCE |
CORS_ORIGINS |
ALIAS_AUTO_MAP_THRESHOLD, ALIAS_REVIEW_THRESHOLD |
SEED_ADMIN_EMAIL, SEED_ADMIN_PASSWORD |
SHIFT_1_START, SHIFT_2_START, TIMEZONE, MAX_UPLOAD_MB |
Thresholds also live in the app_settings table, which takes precedence at runtime; the environment values are bootstrap defaults so a fresh database is usable.
ANTHROPIC_API_KEY and database credentials are server-side only and must never reach the browser bundle.
9. Definition of done for a server change
- You ran no git or GitHub command. Changes are left on disk, uncommitted, for a human to review.
-
npm run checkpasses. - Tests pass, including test group C (golden values).
- New or changed endpoints are reflected in the OpenAPI spec in
docs/system-design/09-api-contract.md ยง5. - Mutations emit an
audit_eventsrecord with actor, before-state, and after-state. - Analytical responses carry
meta.provenance. - Nothing returns
0where the honest answer isnull. - If behaviour diverged from the design, the relevant document in
docs/system-design/was updated in the same change โ the design documents are the specification, not a historical record.