# Permissions

Admin commands, voice permission nodes and per-loader permission backends

Source: https://socketsvc.vercel.app/server/permissions
## Admin commands

| Command | Purpose |
| --- | --- |
| `/ssvc-server`, `/ssvc-server help [page]` | The help menu: the version, and every command with a line on what it does. Click a command to put it in the chat box, hover it for its full syntax, and use the arrows to turn the page |
| `/ssvc-server status` | Shows the actual listener address, whether a reload is in progress, the public URL and the number of connected voice clients; while the listener runs it also lists hearing range, fade start, the spectator rule, `visible-players-only`, the soundboard switch, relay queue drops (overflow/expired/closed), and how many players are muted |
| `/ssvc-server reload` | Re-reads and applies the config file and the [messages file](/server/messages); see [Hot reload](/server/configuration#hot-reload) |
| `/ssvc-server settings [set <name> <value>]` | Lists the everyday settings, and changes one by name; a change is saved to the config file with its comments kept and reloaded. See [Changing settings by command](/server/configuration#changing-settings-by-command) |
| `/ssvc-server test <player>` | Pings one player's voice connection and reports what the server knows about their session; see [Testing a player's connection](#testing-a-players-connection) |
| `/ssvc-server groups ...` | Lists, creates, disbands and retypes [voice groups](/server/groups), and moves players between them; see [Commands](/server/groups#commands) |
| `/ssvc-server mute <player> [duration] [reason...]` | Stops a player talking, for a while or until lifted; see [Moderation](/server/moderation) |
| `/ssvc-server unmute <player>` | Lifts an individual mute |
| `/ssvc-server mutes` | Lists everybody currently muted |
| `/ssvc-server mute-all <on\|off>` | Silences everybody without `socketsvc.mute.exempt` |

All of them require the `socketsvc.admin` permission, which ops have by default; the `/` can be omitted in the console. The four mute commands require `socketsvc.admin.mute` as well, so moderation can be handed out without the rest of the console. All core server settings can be applied through reload, and a connection address change triggers automatic voice reconnects.

## Testing a player's connection

`/ssvc-server test <player>` answers the question status cannot: is *this* player's voice actually working? It sends a real WebSocket ping to their client and waits up to 3 seconds for the pong, then reports the round trip together with everything the server already knows about their session.

```text
> /ssvc-server test Alex
Pinging Alex's voice connection...
SocketSVC connection test: Alex
  Result: connected and responding
  Round trip: 42 ms
  Remote address: /203.0.113.7:51234
  Audio protocol: v2 (sequenced, loss concealment)
  Extensions: spatial=true, status=true, soundboard=true
  Self deafened: false, speaking now: false
  Permissions: speak=true, listen=true, soundboard=true
  Server mute: none
  Audible to 3 player(s); can hear 3 player(s)
  Queued frames: 0
```

The player name must be an exact, case-sensitive match against someone online; tab completion offers online names. The command answers asynchronously — the pong arrives on a network thread — so it never blocks the server, and two admins testing the same player share one ping rather than making the client answer twice.

### Reading the result

The first line is the verdict; the rest is the evidence behind it.

| Result | Meaning |
| --- | --- |
| `connected and responding` | The link is healthy end to end |
| `connected and responding (deafened by choice)` | Healthy; they have deafened themselves in the client |
| `connected but not answering (link may be dead)` | The socket is open but no pong came back in 3 s — a half-open connection, a stalled tunnel, or a frozen client |
| `connected, but muted by the server (...)` | The link works; they are [muted](/server/moderation), and the brackets say for how long, by whom and why |
| `connected, but not allowed to speak` / `to listen` / `blocked from speaking and listening` | The link works; a [permission node](#permission-nodes) is blocking audio |
| `no voice connection` | They are online in Minecraft with no voice session at all |

`no voice connection` is the common one, and the server genuinely cannot tell its causes apart from here — the client either never reached it or never tried. The usual three are: no SocketSVC client mod installed, a `public-url` that is unreachable from the player's network (see [Configuration](/server/configuration#fields)), or first-time setup never finished. The report prints them as a reminder.

The remaining lines are for narrowing down audio problems that are not connectivity problems:

- **Audio protocol** — `v1` means an older client with no packet-loss concealment, which sounds choppier on a lossy link.
- **Extensions** — `status=false` means the client cannot report deafen; `spatial=false` means plugin speakers will not reach them.
- **Audible to / can hear** — how many connected players are in range of them right now, and vice versa, applying every rule the relay applies. Both being 0 while others are connected points at range, worlds, `visible-players-only` or spectator mode rather than at the connection.
- **Server mute** — `none`, or the mute in force with its remaining time, who issued it and the reason. This is usually the answer when a player says they can hear everyone and nobody can hear them.
- **Queued frames** — a persistently non-zero backlog means the socket is not draining as fast as audio arrives, i.e. the player's downstream link is saturated.

<Callout title="Self-mute is not in the report">
A player's *own* microphone mute is enforced entirely in the client, which never tells the server about it, so `speaking now` is the only honest signal — a self-muted player simply never relays a frame. Deafen *is* reported, because it changes what the server routes. The same distinction applies to [placeholders](/server/placeholders).

A **server mute** is a different thing entirely and the server does know about it: see [Moderation](/server/moderation), and `/ssvc-server mutes` for the list.
</Callout>

## Permission nodes

| Node | Default | Purpose |
| --- | --- | --- |
| `socketsvc.admin` | op | Use `/ssvc-server` |
| `socketsvc.speak` | `true` (everyone) | Transmit microphone audio |
| `socketsvc.listen` | `true` (everyone) | Receive other players' voice |
| `socketsvc.soundboard` | `true` (everyone) | Trigger soundboard clips |
| `socketsvc.groups` | `true` (everyone) | Join and leave [voice groups](/server/groups) |
| `socketsvc.groups.create` | `true` (everyone) | Create a voice group |
| `socketsvc.groups.admin` | op | Join a password-protected group without the password, and disband or retype anyone's group |
| `socketsvc.admin.mute` | op | Use the [mute commands](/server/moderation#commands) |
| `socketsvc.mute.exempt` | op | Keep talking through a server-wide mute, and cannot be muted individually |
| `socketsvc.require.exempt` | op | Never refused by [`require-client`](/server/configuration#requiring-the-client-mod) |
| `socketsvc.bridge` | `true` (everyone) | Allow this player's microphone to reach a plugin through the [microphone tap](/server/spatial-audio-api#microphone-tap-api-version-4) |

`socketsvc.speak`/`socketsvc.listen`/`socketsvc.soundboard` can be revoked for individual players or groups through a permissions plugin (such as LuckPerms):

- **`socketsvc.speak`** revoked: that player's microphone audio is never relayed to anyone. This is the right tool for a standing policy; for silencing a person who is doing something now, use a [mute](/server/moderation) instead — it carries a reason, an expiry and a notice the player can actually see.
- **`socketsvc.listen`** revoked: that player receives no voice from any other player — a server-side forced deafen, independent of the client's own deafen setting.
- **`socketsvc.soundboard`** revoked: soundboard frames triggered by that player are dropped by the server before routing, without disconnecting. This blocks the player or group regardless of what the client does.

### Group permissions

The three group nodes only matter while [voice groups](/server/groups) are switched on in the config; with `groups.enabled` false the capability is never negotiated and none of them is ever consulted.

- **`socketsvc.groups`** revoked: no group menu, and any group request from that player is refused (it does not disconnect them) — except leaving, which stays allowed so someone already in a group when the node is taken away is not stuck in it.
- **`socketsvc.groups.create`** revoked: they can join groups other people made but cannot make one. `groups.allow-player-created: false` does the same thing to everyone at once.
- **`socketsvc.groups.admin`** granted: they bypass group passwords and may disband or retype any group. It is the only one of the three that fails **closed** for a player the permission cache has not seen yet.

Each client is told what that player may do as part of the group snapshot, so its menu hides what would be refused — but every request is checked again on arrival, so the menu is a courtesy and not the enforcement.

### The bridge permission

`socketsvc.bridge` decides whose voice may leave SocketSVC for a plugin through the [microphone tap](/server/spatial-audio-api#microphone-tap-api-version-4) — a voice-mod bridge, a Discord relay, recording or transcription.

It does nothing at all unless an operator has set `microphone-tap.enabled: true`. That switch is what keeps the feature off, which is why this node defaults to `true` rather than to op: a node defaulting to false would leave an operator who deliberately turned the switch on still hearing nothing, with nothing to say why.

- **`socketsvc.bridge`** revoked: that player's microphone is never handed to any tap. They talk and are heard by the room exactly as before — this removes them from the tap, not from voice chat.
- It is checked **per frame**, not once when a plugin subscribes, against a permission answer SocketSVC refreshes every second. Revoking it stops that player's audio within a second rather than at their next reconnect.
- It fails **closed** for a player the permission cache has not seen yet — the opposite of `socketsvc.speak`. Not having been checked yet is not consent.

A tap is fed from the same point the relay is, after the mute check and after `socketsvc.speak`, so a muted or silenced player is silent to a tap too. Soundboard and instrument audio are not tapped.

The [Cross System Bridge](/server/cross-system-bridge) reads this node for players on **both** mods. A Simple Voice Chat player holds no SocketSVC session for `socketsvc.speak` to be checked against, so `socketsvc.bridge` is what decides whether SocketSVC players hear them — and that direction does not need `microphone-tap.enabled`, so revoking the node is how you keep one Simple Voice Chat player out of it.

<Callout type="warn" title="On a server mod, excluding somebody needs a permission mod">
  Fabric/NeoForge/Forge fall back to "everyone" for the non-admin nodes when no permission mod is installed, and `socketsvc.bridge` is no exception. So on a bare loader server, turning `microphone-tap.enabled` on taps **everybody**, with no way to exclude one player until you install LuckPerms or an equivalent. Paper reads its default from `plugin.yml` and behaves the same way, but a permission plugin is far more likely to already be there.
</Callout>

### Soundboard permission

The soundboard is an audio channel independent of the microphone: muting the mic does not silence it, but a **listener's** own deafen state still blocks it, the same way it blocks mic audio (both go through the same `canListen` check). For the player-side soundboard guide, see [Soundboard](/client/soundboard).

- The hot-reloadable `soundboard-enabled` setting is a server-wide switch, `true` by default. When disabled, the server still negotiates the dedicated protocol but drops every soundboard frame, so clients cannot fall back to the microphone channel to bypass it.
- Per-player `socketsvc.soundboard` checks apply only while the global switch is enabled.
- For protocol and routing details, see [Voice protocol](/server/voice-protocol#permission).

## Caching and when changes apply

These permissions are read when a player joins and then cached, refreshed once a second per player, so a change takes effect within a second, with no reconnect or `/ssvc-server reload` needed. (They used to be re-read every tick, which cost a server nine permission lookups per player twenty times a second for answers that rarely change.) A player who has just joined and has not been read yet is allowed (fail-open).

## Action bar notices

When a permission blocks a player, an English notice is shown in the action bar:

| Situation | Notice |
| --- | --- |
| Actually trying to speak without `socketsvc.speak` | `You don't have permission to speak in voice chat.` |
| Missing `socketsvc.listen` while another player would otherwise be audible | `You don't have permission to hear voice chat right now.` |
| Triggering the soundboard without `socketsvc.soundboard` | `You don't have permission to use the soundboard.` |
| Trying to talk while [muted](/server/moderation) | `You are muted in voice chat for another 1h 58m: <reason>` |
| Trying to talk while `mute-all` is on | `Voice chat is muted for everyone right now.` |

Notices are shown only when something is actually blocked: the `listen` notice only appears when the audio would otherwise have been audible, not for speakers out of range, deafened or not visible. Each reason has a 5-second cooldown per player to avoid spam.

## Permission backends per loader

| Server side | Permission backend | Default behaviour |
| --- | --- | --- |
| Paper | Bukkit permissions (declared in `plugin.yml`), overridable by permission plugins such as LuckPerms | `admin` defaults to op; other nodes default to `true` |
| Fabric/Quilt | fabric-permissions-api (bundled), works with permission mods such as LuckPerms | Without a permission mod it falls back to op levels: `admin` needs op level 2, other nodes allow everyone |
| NeoForge/Forge | Each loader's PermissionAPI, with nodes `socketsvc.admin`, `socketsvc.speak`, `socketsvc.listen`, `socketsvc.soundboard`, overridable by permission mods | `admin` requires op (gamemaster permission) by default, other nodes allow everyone; the console is checked by op permission |

## Addon permissions

Addon plugins built on the [Spatial audio API](/server/spatial-audio-api) can define their own permissions for their own commands. For example, the optional speaker example plugin uses `socketsvc.speaker.admin`, default op.