# Departments and permissions

Every faction that uses the MDT is one entry in `Config.Departments` in `shared/departments.lua`. A player's framework job decides which department they belong to. That department sets their permissions, crest and tablet theme. Adding a faction needs no code.

A job that is not listed in any department has no MDT access. A job may appear in only one department.

## Department fields

| Field | Required | Description |
|---|---|---|
| `label` | yes | Full name, shown on papers, mail and the roster. |
| `short` | yes | Short tag such as `LSPD`. Shown in the top bar, on badges and in document numbers. Defaults to the id in upper case. |
| `jobs` | yes | Framework job names that belong to this department. |
| `type` | yes | `leo`, `doj`, `ems`, `fire` or `other`. Aliases: `police` and `sheriff` become `leo`, `medical` and `ambulance` become `ems`, `justice` becomes `doj`. Anything else becomes `other`. |
| `color` | no | Department color (hex). Used for unit dots, tags and the tablet accent. |
| `logo` | no | A built-in crest key or an image URL (`https://...`, `nui://...`). |
| `motto` | no | Printed on citations and forms. |
| `callsignPrefix` | no | Prefix for automatic callsigns, for example `1-`. |
| `citationPrefix` | no | Citation number prefix. `Config.Citations.prefixes[id]` takes precedence. |
| `theme` | no | Tablet look. A string works as a preset: `theme = 'ems'`. |
| `ranks` | no | `[minGrade] = accessLevel`. The highest `minGrade` at or below the player's grade wins. |
| `bossRank` | no | Access level for boss grades. |
| `defaultRank` | no | Used when no `ranks` entry matches. |
| `jobRanks` | no | `[jobName] = accessLevel`. Fixes the level for one job regardless of grade. DOJ uses it for `lawyer`, `da`, `clerk` and `judge`. |
| `permissions` | no | `[accessLevel] = { 'perm', ... }` or `[accessLevel] = 'presetName'`. Gives this department its own permission list for a level. |
| `statuses` | no | Own unit status list `{ id, code, color }`, replacing the default list for this department. |
| `field` | no | `true` or `false`. Field departments can go on duty, appear on the unit board and live map, and receive dispatch calls. Defaults to `true` for `leo`, `ems` and `fire`. |

Departments missing from `Config.DepartmentOrder` are added at the end in alphabetical order, so the order list is optional.

## Adding a department

::::steps
### Add the entry

```lua title="shared/departments.lua"
lsfd = {
    label = 'Los Santos Fire Department',
    short = 'LSFD',
    type = 'fire',
    jobs = { 'fire', 'firefighter' },
    color = '#F97316',
    logo = 'fire',
    motto = 'Courage and Honor',
    callsignPrefix = 'F-',
    theme = 'fire',
},
```

### Add it to the order list (optional)

```lua title="shared/departments.lua"
Config.DepartmentOrder = { 'lspd', 'bcso', 'sahp', 'doj', 'ems', 'lsfd' }
```

### Restart the resource

Players with one of the listed jobs now see the MDT with the new department.
::::

A custom faction with its own permissions:

```lua title="shared/departments.lua"
rangers = {
    label = 'San Andreas Park Rangers',
    short = 'SAPR',
    type = 'other',
    field = true,
    jobs = { 'ranger' },
    color = '#22C55E',
    logo = 'https://example.com/rangers.png',
    theme = { preset = 'custom', accent = '#22C55E', surface = '#0c1510' },
    ranks = { [0] = 'ranger', [4] = 'chief' },
    bossRank = 'chief',
    permissions = {
        ranger = { 'dashboard.view', 'roster.view', 'mail.use', 'calendar.view', 'dispatch.view', 'citizens.view' },
    },
},
```

You can also create and edit departments live from the Admin panel when `Config.Admin.departmentOverrides` is on. Changes from the panel are stored in the database table `koja_mdt_department_overrides` and merged over the file.

## Ranks and access levels

A department maps framework grades to an access level. The access level decides the permission set.

| Level | Meant for |
|---|---|
| `cadet`, `officer`, `supervisor`, `command` | Law enforcement. `command` has every permission except `admin.manage`. |
| `defense`, `prosecutor`, `clerk`, `judge` | DOJ. |
| `responder`, `responder_lead`, `responder_chief` | EMS and fire. |
| `member`, `lead`, `chief` | Other factions (non-field by default). |

Default `ranks` by type, used when a department does not define its own:

| Type | Default |
|---|---|
| `leo` | `[0] = 'cadet'`, `[1] = 'officer'`, `[3] = 'supervisor'`, `[5] = 'command'` |
| `doj` | `[0] = 'defense'`, `[1] = 'prosecutor'`, `[2] = 'clerk'`, `[3] = 'judge'` |
| `ems`, `fire` | `[0] = 'responder'`, `[3] = 'responder_lead'`, `[5] = 'responder_chief'` |
| `other` | `[0] = 'member'`, `[3] = 'lead'`, `[5] = 'chief'` |

How the level is resolved for a player:

1. If the department has `jobRanks[job]`, that level is used.
2. If the player is a boss grade, `bossRank` is used. Defaults: `leo` is `command`, `ems` and `fire` are `responder_chief`, `other` is `chief`.
3. Otherwise the `ranks` entry with the highest `minGrade` at or below the grade is used.
4. If nothing matches: `defaultRank`, then `cadet` (leo), `defense` (doj), `responder` (ems, fire) or `member`.

### What each level can do

| Level | Summary |
|---|---|
| `cadet` | View the main record pages, create reports and evidence, view, create and print citations. |
| `officer` | Cadet plus edit people, vehicles, firearms and reports, process suspects, request warrants, create BOLOs, manage dispatch, view cameras and bodycams, view custody and create impounds. |
| `supervisor` | Officer plus revoke licenses, restricted and deletable reports, delete warrants, BOLOs and evidence, manage bulletins, view logs, review forms, discipline, manage the calendar, void citations, watch and manage bodycams, manage jail and release impounds. |
| `command` | Every permission except `admin.manage`. |
| `defense` | Court view, bar registry view, expungement requests, people and report view, charges, bulletins, mail, forms and calendar. |
| `prosecutor` | Defense plus case management, vehicles, firearms, warrants view, evidence view, roster view, citations view, bodycams view and jail view. |
| `clerk` | Defense plus case management, hearing scheduling, bar registry management, warrants view, roster view, citations view, forms review, calendar management and jail view. |
| `judge` | Prosecutor plus approve and delete warrants, restricted reports, manage charges and bulletins, view logs, review forms, mail broadcasts, manage calendar, void citations, schedule hearings, rule on cases, review expungements, manage the bar registry. |
| `responder` | Dashboard, roster, mail, calendar, bulletins, divisions, certifications, forms, dispatch view. EMS departments also get the medical permissions. |
| `responder_lead` | Responder plus dispatch management, bulletins and calendar management, form reviews, logs, discipline. |
| `responder_chief` | Lead plus hire and fire, suspend, manage divisions, certifications and forms, mail broadcasts. |
| `member`, `lead`, `chief` | The same as the responder levels without dispatch. |

The default EMS and fire levels do not include `citizens.view` or `incidents.view` because those pages show criminal records. Add them through `permissions` if your server wants medics to see them.

Every permission is checked on the server for each request. The interface only hides what the player cannot use. Pages without permission are hidden from the navigation, and opening them directly shows a no permission screen.

## Permission list

Permission keys are written in the form `page.action`. Players hold permissions through their access level.

### People, vehicles and records

| Permission | Allows |
|---|---|
| `dashboard.view` | Open the dashboard. |
| `citizens.view` | View people and their files. |
| `citizens.edit` | Edit a person's file, flags and photos. |
| `licenses.revoke` | Revoke and reinstate licenses. |
| `vehicles.view` | View and search vehicles. |
| `vehicles.edit` | Edit vehicle flags and notes. |
| `weapons.view` | View the firearm registry. |
| `weapons.edit` | Register and edit firearms. |
| `incidents.view` | View reports. |
| `incidents.create` | Write reports. |
| `incidents.edit` | Edit reports. |
| `incidents.delete` | Delete reports. |
| `incidents.restricted` | View restricted reports. |
| `incidents.process` | Process suspects (fine, jail, points). |
| `charges.view` | View the penal code. |
| `charges.manage` | Edit the penal code. |

### Warrants, BOLOs, evidence

| Permission | Allows |
|---|---|
| `warrants.view` | View warrants. |
| `warrants.create` | Request or create warrants. |
| `warrants.approve` | Approve or deny pending warrants (judges). |
| `warrants.delete` | Delete warrants. |
| `bolos.view` | View BOLOs. |
| `bolos.create` | Create BOLOs. |
| `bolos.delete` | Delete BOLOs. |
| `evidence.view` | View the evidence locker. |
| `evidence.create` | Add evidence. |
| `evidence.delete` | Delete evidence. |

### Dispatch, citations, custody

| Permission | Allows |
|---|---|
| `dispatch.view` | View calls and the unit board. |
| `dispatch.manage` | Create, assign and close calls. |
| `citations.view` | View citations. |
| `citations.create` | Write citations. |
| `citations.print` | Print citations as an item. |
| `citations.void` | Void citations and resolve contests. |
| `jail.view` | View jail records. |
| `jail.manage` | Release early, change terms, transfer. |
| `impound.view` | View impounds. |
| `impound.create` | Impound vehicles. |
| `impound.release` | Release impounded vehicles. |

### Court and DOJ

| Permission | Allows |
|---|---|
| `court.view` | View the docket. |
| `court.manage` | File and edit cases, charges and links. |
| `court.schedule` | Schedule hearings. |
| `court.rule` | Verdicts, sentences, carrying out a sentence. |
| `expunge.request` | Request expungement. |
| `expunge.review` | Decide expungement requests. |
| `bar.view` | View the bar registry. |
| `bar.manage` | Manage the bar registry. |

### Staff, communication, surveillance

| Permission | Allows |
|---|---|
| `bulletins.view` | View bulletins. |
| `bulletins.manage` | Create and edit bulletins. |
| `roster.view` | View the employee list. |
| `roster.manage` | Hire, fire, promote and demote. |
| `roster.discipline` | Give rewards and strikes. |
| `roster.suspend` | Suspend and reinstate members. |
| `logs.view` | View the audit log. |
| `mail.use` | Use internal mail. |
| `mail.broadcast` | Send mail to whole departments. |
| `divisions.view` | View divisions. |
| `divisions.manage` | Create and edit divisions. |
| `certifications.view` | View certifications. |
| `certifications.manage` | Create certifications, assign and revoke. |
| `forms.view` | View and fill forms. |
| `forms.manage` | Build forms. |
| `forms.review` | Approve or reject submissions. |
| `calendar.view` | View the calendar. |
| `calendar.manage` | Create and edit events. |
| `cameras.view` | Watch CCTV cameras. |
| `cameras.manage` | Manage cameras. |
| `bodycams.view` | View bodycam sessions. |
| `bodycams.watch` | Watch bodycams live. |
| `bodycams.manage` | Manage bodycam sessions. |
| `admin.view` | View the Admin panel. |
| `admin.manage` | Change things in the Admin panel. Not part of `command`; given through the `koja-mdt.admin` ace or explicitly. |

### Medical

Only granted to `ems` departments, or through `permissions` in other departments.

| Permission | Granted to |
|---|---|
| `patients.view`, `patients.edit`, `treatments.view`, `treatments.create`, `hospital.view`, `hospital.manage`, `bills.view`, `bills.create` | `responder` and up |
| `treatments.edit`, `bills.void` | `responder_lead` and up |
| `treatments.delete` | `responder_chief` |
| `patients.summary` | Read-only medical summary on the People page. Granted to police access levels listed in `Config.Ems.policeSummary.ranks`, only when `Config.Ems.policeSummary.enabled = true`. Every view is logged. |

Bodycams and CCTV cameras without a department list also require a law enforcement department.

## Boss grades

Boss grades come from the framework (the boss flag of the job grade). A boss in a department gets its `bossRank` instead of the grade based level. Set `bossRank` explicitly if the default does not suit you. `jobRanks` takes precedence over the boss rule.

## Custom permission lists

Use `permissions` in a department to override one level:

```lua title="shared/departments.lua"
permissions = {
    officer = 'supervisor',                 -- use another preset for this level
    cadet = { 'dashboard.view', 'mail.use' } -- or an explicit list
}
```

Unknown keys are ignored. The Admin panel can also edit these lists per department.

## Themes and logos

`logo` accepts these built-in crests: `lspd`, `bcso` (also `sheriff`, `star`), `sahp` (`trooper`, `wings`), `doj` (`justice`, `scales`), `ems` (`medical`, `ambulance`), `fire` (`lsfd`, `maltese`), `shield` (`police`). Unknown keys use the generic shield. Any `https://` or `nui://` image URL also works.

`theme` switches the tablet look:

```lua title="shared/departments.lua"
theme = { preset = 'bcso' }
theme = { preset = 'custom', accent = '#22C55E', surface = '#0c1510' }
theme = { preset = 'ems', accent = '#F43F5E' }
```

| Preset | Look |
|---|---|
| `lspd` / `neutral` | Default neutral dark tablet with the department color as accent. |
| `bcso` | Warm tan and olive dark surfaces. |
| `sahp` | Cool steel blue dark surfaces. |
| `doj` | Deep burgundy charcoal. |
| `ems` | Dark red tinted surfaces. |
| `fire` | Dark ember red and orange surfaces. |
| `custom` | Nothing preset. Only your `accent` and `surface` apply. |

- `accent` is the highlight color (buttons, active tabs, toggles). Defaults to `color`.
- `surface` is the base screen color (hex). All other surfaces are derived from it. Keep it dark, roughly `#0e0e10` to `#221012`.

If `theme` is omitted, the preset is picked from the department id, then from `logo`, then from `type`. A player's personal accent (Settings, when `Config.Ui.allowPersonalAccent` is on) overrides the accent but not the surfaces.

## DOJ

Court options live in `Config.Doj`. Parties assigned to a case (judge, prosecutor, defense) can add docket filings and link records even without `court.manage`. Carrying out a sentence uses the fine and jail adapters in `editable/server/integrations.lua`. See [Integrations](/new/mdt/integrations).

## Dispatch for EMS and fire

Field departments receive calls that target them. Calls with no target go to law enforcement only. Create calls from your own scripts with the server export, see [Server exports](/new/mdt/api/server-exports). Calls created from the MDT by a non-police department are sent to that department.
