Update root and per-directory AGENTS.md files to reflect the current state of the codebase: collection inventory, RBAC registry, base management, personnel pages, training minigames, Discord bot transfer and evaluation-reminder flows, banking currency config, migration wrapper, and Playwright/Vivaldi e2e details.
6.7 KiB
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-configin files undermarket/npcDialogue.tsormarket/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.tsfor cross-instance scenarios — use external pub/sub (Redis) instead - NEVER mutate
storageRules.tsenforcement order without updating all 3 call sites (structure actions, shipment creation, arrival processing)