docs: document oper classes/types + the five built-in types (operators.md, example config)

This commit is contained in:
Jean Chevronnet 2026-08-20 10:06:38 +00:00
parent 01516d5fdc
commit 81e013f053
No known key found for this signature in database
GPG key ID: 439666D63A9477E4
2 changed files with 51 additions and 1 deletions

View file

@ -26,6 +26,44 @@ An `oper` block may carry a trailing numeric **level** (`oper = <name> <pass>
be `KILL`ed by a lower-level one. Levels are advisory policy layered on top of the be `KILL`ed by a lower-level one. Levels are advisory policy layered on top of the
`+o` flag. `+o` flag.
### Oper types
An `oper` block can name a **type** with `type=<id>` — a role that decides what the
oper may actually do, what usermodes and snomasks they get on oper-up, and how their
`/WHOIS` reads (`is a <title>`). An oper with **no** `type` keeps full access (every
oper command), so existing blocks are unaffected.
A type is built from reusable **classes** — capability bundles:
```text
# class = <id> commands=<A,B,|*> [privs=<x,y|*>] [snomasks=<letters|*>]
class = ban commands=KILL,KLINE,GLINE,ZLINE,QLINE,ELINE,RLINE,SHUN,CBAN,CHECK snomasks=kx
class = announce commands=WALLOPS,GLOBOPS snomasks=ag
class = override commands=SAJOIN,SAPART,SANICK,SAKICK,SAMODE,SATOPIC,SAQUIT,CLEARCHAN privs=override
# opertype = <id> classes=<a,b|*> [commands=…] [modes=+iw] [snomasks=+cg] \
# [vhost=host.name] [title=Nice_Title] [level=N]
opertype = netadmin classes=* modes=+iw snomasks=+* title=Network_Administrator level=100
oper = alice sha256:<hex> type=netadmin
```
`commands`, `privs`, `snomasks`, and `classes` accept `*` for "all". A type's `modes`
and `snomasks` are set automatically at oper-up; `vhost` (if given) replaces the host;
`title` (underscores become spaces) is the `/WHOIS` line; `level` folds into the
[oper level](#oper-levels). Running a command the type doesn't grant is refused.
Five types ship **built-in**, so `type=<id>` works with no `class`/`opertype` config —
override or extend any by defining one with the same id:
| id | title | grants |
|----|-------|--------|
| `helpop` | Help Operator | +ih, oper snomask — a titled helper, no privileged commands |
| `globop` | GlobOp | + `WALLOPS`/`GLOBOPS` + announce snomasks |
| `admin` | Administrator | + `KILL`/x-lines/`SHUN`/`CHECK`, `SA*` override, `CHG*`/`SET*` |
| `servadmin` | Services Administrator | + the `SVS*` services commands |
| `netadmin` | Network Administrator | everything, plus `CONNECT`/`SQUIT`/`DIE`/`RESTART` |
## Snomasks ## Snomasks
Server-notice masks (`+s`) subscribe an oper to categories of the server's live Server-notice masks (`+s`) subscribe an oper to categories of the server's live

View file

@ -51,9 +51,21 @@ bind_server = 0.0.0.0:7000
# restricts which source IP may use the password (recommended). Repeat for more. # restricts which source IP may use the password (recommended). Repeat for more.
# webirc = CHANGE_THIS_WEBIRC_SECRET mygateway 203.0.113.9 # webirc = CHANGE_THIS_WEBIRC_SECRET mygateway 203.0.113.9
# IRC operators — oper = <name> <password> # IRC operators — oper = <name> <password> [level] [fp=<sha256>] [type=<id>]
oper = admin CHANGE_THIS_PASSWORD oper = admin CHANGE_THIS_PASSWORD
# Oper types (optional). An oper with no type= keeps full access. A type is a
# named role (the WHOIS "is a <title>") built from reusable capability classes;
# five ship built-in: helpop, globop, admin, servadmin, netadmin. Override or add
# your own — see docs/operators.md. Running a command your type doesn't grant is
# refused; the type's modes/snomasks/vhost are set automatically on oper-up.
# class = <id> commands=<A,B|*> [privs=<x,y|*>] [snomasks=<letters|*>]
# opertype = <id> classes=<a,b|*> [commands=..] [modes=+iw] [snomasks=+cg] \
# [vhost=host.name] [title=Nice_Title] [level=N]
# class = helpdesk commands=CHECK snomasks=c
# opertype = helpdesk classes=helpdesk modes=+ih title=Help_Desk level=15
# oper = alice sha256:<hex> type=netadmin
# host-cloaking secret (+x). Use a long random hex string; keep it private. # host-cloaking secret (+x). Use a long random hex string; keep it private.
# Changing it re-cloaks everyone. # Changing it re-cloaks everyone.
cloak_key = CHANGE_THIS_TO_A_LONG_RANDOM_HEX_STRING cloak_key = CHANGE_THIS_TO_A_LONG_RANDOM_HEX_STRING