# Permissions

## Check Permission

### `player:HasPermission(node)`

Server-side O(1) permission check.

```lua
local player = Nova.Functions.GetPlayer(source)

if player:HasPermission('admin.kick') then
    -- Allowed
end

if player:HasPermission('*') then
    -- Only superadmin has wildcard
end
```

| Parameter | Type     | Description                            |
| --------- | -------- | -------------------------------------- |
| `node`    | `string` | Permission node (e.g., `'admin.kick'`) |

**Returns:** `boolean`

## Group Management

### `player:GetGroup()`

```lua
local group = player:GetGroup()
-- Returns: 'superadmin', 'admin', 'moderator', 'user'
```

### `player:SetGroup(group)`

```lua
player:SetGroup('admin')
```

## Permission Nodes

| Node             | Description                  |
| ---------------- | ---------------------------- |
| `*`              | All permissions (superadmin) |
| `admin.kick`     | Kick players                 |
| `admin.ban`      | Ban players                  |
| `admin.teleport` | Teleport self/others         |
| `admin.give`     | Give items/money             |
| `admin.spawn`    | Spawn vehicles               |
| `admin.noclip`   | Toggle noclip                |
| `admin.setgroup` | Change player groups         |
| `admin.announce` | Server announcements         |

## Configuration

Groups and their permissions are defined in `nova_core/config/groups/admin.lua`:

```lua
Config.AdminGroups = {
    ['superadmin'] = {
        label = 'Super Admin',
        level = 100,
        permissions = {'*'},
    },
    ['admin'] = {
        label = 'Admin',
        level = 80,
        permissions = {
            'admin.kick', 'admin.ban', 'admin.teleport',
            'admin.give', 'admin.spawn', 'admin.noclip',
            'admin.setgroup',
        },
    },
}
```

## Performance

Permissions use a hash table (O(1) lookup):

```lua
-- Internally cached as:
cache['admin.kick'] = true
cache['admin.ban'] = true

-- player:HasPermission('admin.kick') is just:
-- return cache['admin.kick'] == true
-- This is O(1), not O(n)
```
