> For the complete documentation index, see [llms.txt](https://assetdocs.ezekieljds.com/scripts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://assetdocs.ezekieljds.com/scripts/mi_fire/getting-started/permissions.md).

# Permissions

## The short version

**If you run Qbox, the fire commands already work for your admins.** mi\_fire grants itself to `group.admin` and `group.god` at boot, which is the same group Qbox gates its own admin commands on. No `server.cfg` edit needed.

If `/fire` refuses you, run:

```
/fire perms
```

It reports every permission it checked, what you actually hold, and the exact line to add if you need one. That command is deliberately available to everyone — the person who cannot use the commands is exactly who needs to see why.

***

## Two ways in

They answer different questions, and they work independently.

| Route             | Answers                         | Who it is for                        |
| ----------------- | ------------------------------- | ------------------------------------ |
| **ACE**           | Is this a server administrator? | Staff testing or cleaning up         |
| **Job and grade** | Is this the fire chief?         | Officers running drills in character |

A server admin does not need to clock on as a firefighter to test a scene. A fire chief does not need server admin to run a drill. Neither route requires the other.

## ACE access

```lua
-- config/config.lua
Config.permissions = {
    aces = { 'mi_fire.admin', 'command.fire' },
    principals = { 'group.admin', 'group.god' },
}
```

`principals` is the convenient part: at boot, mi\_fire grants its ACE to each of those groups. Since `group.admin` already exists on any Qbox server, your admins get access with no configuration.

To turn that off and require an explicit grant instead, empty the list and add your own:

```cfg
add_ace group.admin mi_fire.admin allow
```

Any single ACE in `aces` is enough. `command.fire` is there because that is the ACE ox\_lib would use if you ever restricted the command yourself.

## Job and grade access

```lua
Config.permissions = {
    jobs = {
        fireman = 4,        -- grade 4 and above
    },
    jobsRequireOnDuty = false,
}
```

A player whose job is listed and whose grade is at or above the number gets access. Grades come from your framework, so `4` means whatever grade 4 is on your server — check your job definitions rather than guessing.

`jobsRequireOnDuty` is separate from `Config.requireOnDuty` on purpose. The default is `false`, so an off-duty chief can still stop a runaway fire. Set it to `true` if you want rank to only count while clocked on.

### Limiting what rank unlocks

```lua
    jobCommands = {
        'here', 'start', 'at', 'stop', 'stopall', 'list', 'info', 'agent', 'classes', 'perms',
    },
```

Only these subcommands are reachable through *job* access. ACE admins always get everything.

The default withholds `wind`, which changes weather for the whole server rather than for one incident. Set `jobCommands = nil` to give job holders the full set.

## What refusals look like

mi\_fire tries to tell you which of the two routes failed, because they need different fixes:

| Message                                                   | Means                                           |
| --------------------------------------------------------- | ----------------------------------------------- |
| `not permitted (no matching job)`                         | Neither route. You need an ACE or a listed job. |
| `not permitted (fireman grade 2 is below the required 4)` | Right job, not senior enough.                   |
| `your rank cannot use "wind"`                             | Job access works, but not for that subcommand.  |

All of them are followed by a nudge to run `/fire perms`.

## Protective equipment is not job-gated

Turnout gear and SCBA work for **whoever is wearing them**. A civilian who gets hold of a set is protected by it exactly as much as a firefighter is, because a coat is a coat and a bottle of air works for whoever is breathing it.

The gate is on **obtaining** it, not using it. Taking a set off an apparatus or a station rack is department business and still requires the fire job; what you do with gear you already have is your own affair.

```lua
Config.gearRequiresJob = false
```

Set it true if you would rather protection was a job perk.

Note that protection follows the **clothing**, so however a firefighter got dressed -- the truck, a station locker, an outfit menu, a job clock-in -- the gear works. See [Reading smoke](/scripts/mi_fire/guides/reading-smoke.md) and the gear section of the [configuration reference](/scripts/mi_fire/configuration/configuration.md).

## Firefighters and EMS

Separate from admin access, and not ACE-based. These gate hose lines, the pump panel, and taking equipment off department property — **not** protection, which follows the clothing.

```lua
Config.fireJobs = { fireman = true, fire = true, firefighter = true, lsfd = true }
Config.emsJobs  = { ambulance = true, ems = true, doctor = true }
Config.requireOnDuty = true
```

If your fire job is not in `fireJobs`, nothing in mi\_fire will work for your firefighters. That is the most common installation mistake.

Admins bypass the firefighter check, so staff can test equipment without clocking on.

## No framework

If mi\_fire cannot find Qbox or ESX, it runs standalone. Job access is unavailable because there are no jobs, so ACE is the only route. That is enough to test on a bare server and not enough to run one.
