# AGENTS.md — Shared Business Logic > **Parent**: `../../AGENTS.md` — Payload config, server actions pattern, env vars. ## Overview 63 files across 17 domain subdirectories plus root modules. Contains pure business logic and Payload-dependent service modules. Server actions in route directories delegate here; these modules hold the actual domain rules. ## Structure ``` lib/ utils.ts # cn() class merger (Tailwind) storageRules.ts # Storage validation (prohibited → whitelist → per-item cap) shipping.ts # Fuel cost, transit time, vehicle effective speed distance.ts # Haversine distance calculation logistics.ts # Shared logistics helpers aim-trainer.ts # Pure aim-trainer game rules (difficulties, scoring, XP) impersonation.ts # Admin impersonation cookie helpers redaction.ts # Text redaction helper versionInfo.ts # Build version display arma-bridge/ # Arma server sync: auth, heartbeat/presence, commands, sync events attendance/ # Mission attendance service (single write path) awards/ # Award grant eligibility + diff/notify/cleanup banking/ # Transaction engine, account creation, currency config, formatting base/ # Staffing (hire/fire/headcount), structure upgrades, storage, base tick evaluations/ # Evaluation levels + bot reminder plan (reminders.ts) locker/ # Grid logic, placement validation, loadouts, attachments/skins logistics/ # Mission lifecycle + mission reminder logic market/ # Buy/sell, NPC negotiation, dialogue, vendor resolution notifications/ # User notification helper + muteable types projects/ # Project ticket-type metadata (projectMeta.ts) realtime/ # In-process SSE bus + presence tracking (single-instance only) session/ # Session token expiry helpers shims/ # Shim audience/path evaluation (djb2 hash matching) tickets/ # Ticket vocabulary, Lexical helpers, staff resolution transfers/ # Assignment transfer workflow (request/decide/appeal) + notification types wiki/ # Slugify, templates, wikilinks, markdown pipeline, page service ``` ## Dependency graph ``` Server actions ──┬── storageRules.ts ├── lib/banking/index.ts ──┬── format.ts (CurrencyConfig) │ └── ui.ts ├── lib/market/index.ts ──┬── negotiations.ts │ ├── npcs.ts │ ├── npcDialogue.ts (pure, client-safe) │ └── chatBubbles.ts (pure, client-safe) ├── lib/base/ (staffing.ts, upgrade.ts, tick.ts, storage.ts) ├── lib/wiki/service.ts + prepare.ts (markdown.tsx is pure, client-safe) ├── lib/locker/index.ts ── search.ts ├── lib/tickets/, lib/transfers/, lib/awards/ ├── lib/attendance/index.ts ├── lib/evaluations/ (reminders.ts drives the bot's evaluation DMs) └── lib/notifications/index.ts game-tick script ── shipping.ts, distance.ts, storageRules.ts market-tick script ── lib/market/index.ts (autoPrice, autoQuantity, npc vendor logic) base-tick script ── lib/base/tick.ts (processBaseTick: salaries, maintenance, upkeep) ``` ## Pure vs Payload-dependent - **Pure modules** (no Payload import, safe for client + server): `npcDialogue.ts`, `chatBubbles.ts`, `ticketMeta.ts`, `distance.ts`, `aim-trainer.ts`, `wiki/markdown.tsx`, `wiki/prepare.ts`, `wiki/templates.ts`, `wiki/wikilinks.ts`, `shims/evaluate.ts`, `storageRules.ts` (logic only) - **Payload-dependent** (import `@payload-config`, server-only): everything else ## Key modules ### `storageRules.ts` Enforcement order: **prohibited → whitelist → per-item cap**. Functions: `checkStorageDeposit`, `isResourceProhibited`, `isResourceWhitelisted`, `getResourceStorageCap`, `storageViolationMessage`. Used in structure actions, shipment creation, and arrival processing. ### `banking/index.ts` `applyTransaction()` — single source of truth for balance math. Validates accounts, creates transaction + ledger entries, updates balances. `ensurePersonalAccount()` — dedup find-or-create. `getMainCurrencyId()` — resolves Game Rules main currency. `currencyConfigFromGameRules()` builds the `CurrencyConfig` threaded through banking/market UI. ### `base/` Staffing/upkeep engine for structures: `staffing.ts` (`hireStaff`/`fireStaff`/`setLaborHeadcount`/`assertStaffHiringEnabled`), `upgrade.ts` (`upgradeStructure` — consumes stored materials, swaps type via `upgradesInto`), `storage.ts` (`consumeStorage`/`storedAmount`), `tick.ts` (`processBaseTick` — salaries, maintenance, upkeep flags). ### `market/index.ts` `buyListing()` — validates, debits buyer, credits locker, marks sold. Supports partial buys via `quantity` parameter. `creditLockerQuantity()` — merges stackables or fills empty grid spots; throws if no space. ### `market/negotiations.ts` NPC vendor pricing engine: stance starts at asking price, only moves down. Offers ≥ stance accepted; within 2% with 85% chance; well-below draw concession (30% of gap). Patience meter increments per round, closes at cap. ### `realtime/bus.ts` Module-level subscriber Set. SSE endpoint `GET /api/realtime` subscribes; game tick POST `/api/game-tick/notify` broadcasts. **Single-instance only** — will not work across multiple server processes. ## Where to look | Task | Path | |------|------| | Add storage rule logic | `storageRules.ts` (pure functions) | | Modify transaction flow | `lib/banking/index.ts` — `applyTransaction()` | | Change NPC pricing | `lib/market/negotiations.ts` — NPC_ACCEPT constants | | Add staffing/upkeep logic | `lib/base/` (hire/fire/upgrade/tick) | | Modify minigame rules | `aim-trainer.ts` (pure) or the game's components dir | | Add notification type | `lib/notifications/notificationTypes.ts` | | Add pure client+server logic | Verify no Payload import; place in appropriate domain dir | ## Anti-patterns - **NEVER** import `@payload-config` in files under `market/npcDialogue.ts` or `market/chatBubbles.ts` — they must stay client-safe - **NEVER** duplicate business logic in server actions — always delegate to `lib/{domain}/` - **NEVER** use module-level state in `realtime/bus.ts` for cross-instance scenarios — use external pub/sub (Redis) instead - **NEVER** mutate `storageRules.ts` enforcement order without updating all 3 call sites (structure actions, shipment creation, arrival processing)