# AGENTS.md — Payload Collections > **Parent**: `../../AGENTS.md` — commands, RBAC basics, Payload CMS config. ## Overview 54 files (~53 collections) across 15 domain groups. Access control defined in `src/permissions/index.ts` (~870 lines, permission registry across groups). RBAC check: `hasPermission(payload, user, "collection:action")`. ## Structure ``` collections/ Media.ts # Image uploads (public read; used by wiki image upload) Shims.ts # Global: audience-targeted content (admin-only) users/ 11 files # Users (auth), Ranks, Profiles (incl. minigame stats), Awards, # Qualifications, Assignments, AssignmentTransfers, Experience, # Evaluations, Roles (dynamic RBAC), UserNotifications intelligence/ 5 files # Missions, MissionAttendances, Campaigns, Factions, Technologies logistics/ 5 files # Structures (staffing defaults), Resources, Assets, Vehicles, Shipments banking/ 3 files # BankAccounts, BankTransactions, LedgerEntries market/ 2 files # MarketListings, MarketNegotiations locker/ 2 files # LockerStorages, Loadouts game/ 9 files # GameRules (global, currency + staffing flags), GameStructures, # GameVehicles, GameNpcs, GameHardResources, GameEventLogs, # NpcStaffing, LaborClassifications (+ shared staffingFields.ts factory) server/ 5 files # MissionFiles, ModLists, GameServers, ArmaCommands, ArmaSyncEvents world/ 5 files # Maps (basemap config), MapRoads/MapZones/ResourceNodes (map features), NarrativeEvents projects/ 4 files # Projects, Labels, Releases, Sprints (Jira-like) tickets/ 2 files # Tickets (Lexical rich text), TicketVotes wiki/ 3 files # WikiPages, WikiRevisions, WikiTemplates ``` ## Key relationships ``` Users ──┬── Profiles ──┬── Qualifications │ ├── Awards │ ├── Assignments ── Ranks │ ├── AssignmentTransfers │ └── Experience ├── UserNotifications ├── Evaluations └── BankAccounts ── BankTransactions ── LedgerEntries GameStructures ── Structures (template) ── Resources/Assets/Vehicles GameStructures ── NpcStaffing ── LaborClassifications GameVehicles ── Vehicles (template) GameNpcs ── MarketListings ── MarketNegotiations MissionAttendances ── Missions ── Campaigns ``` ## Access control pattern Collections define `access` at field + document level using helpers from `src/utils/access-control/`: - `isRole(role)` — single role check - `hasRoles(roles[])` — any-of role check - `hasPermission(payload, user, "collection:action")` — full RBAC (cached 30s) - `hasLogisticsQualification()` / `hasIntelligenceQualification()` — queries Profiles Admin group access: `developer` only for destructive operations, `admin` for read/write. ## Hooks with side effects - `Structures` `beforeChange`: emits `structure:resize`; blueprint "Staffing Defaults" group via `staffingFields.ts` - `GameStructures` `afterChange`: emits storage edit events; `beforeChange` copies blueprint staffing defaults on create - `Users` `afterChange`: maintains profile sync - `BankTransactions` `beforeValidate`: auto-generates `transactionNumber` - `MarketNegotiations`: patience meter enforcement ## Where to look | Task | Path | |------|------| | Add a new collection | Create `.ts` here, register in `src/payload.config.ts` | | Add RBAC permission | `src/permissions/index.ts` (add to group + add check) | | Modify collection access | `/access.ts` or inline in collection file | | Add field hook | Inline in collection definition (beforeChange/afterChange) | | Relationship graph | See key relationships above; Payload manages FK constraints | ## Anti-patterns - **NEVER** edit `src/payload-types.ts` or `src/payload-generated-schema.ts` — run `bun run generate:types` instead - **NEVER** add `access` functions that call `payload.auth()` without handling the null user case - **NEVER** use `payload.create` in `afterChange` hooks without checking for infinite loops - **NEVER** mix `overrideAccess: true` without a permission check — always gate behind RBAC first