Trust Tier Model
Audience: Builder Status: ✅ Ready
How TelosMUD grants elevated powers. A trust tier is an ordinal rung on a content-defined ladder, carried on the account, verified into a session at login, and turned into a small set of capability flags by the world. This page covers the world side — the ladder, how a verified tier becomes flags, the reserved-flag denylist, the rank-comparison rules, and what happens to elevation across a cross-shard walk. The account side — where tiers are stored and changed — is in First Admin Setup; the staff verbs the flags unlock are in Builder Commands.
The ladder is content-defined
A tier is { name, rank, flags }: a rank integer (higher = more trusted) and the set of
capability flags that tier grants. The full ladder is content — a pack can define trust_tiers
(see Pack Entity Reference) — and the engine ships a default ladder if a
pack declares none:
| Tier | Rank | Grants |
|---|---|---|
player |
0 | (none) |
builder |
20 | holylight, builder |
admin |
40 | holylight, builder, admin |
The 10/30 gaps are deliberate room for a pack to insert its own rungs between the defaults. A
world uses the pack’s ladder if it declared one, otherwise the shared default.
Rank resolution is fail-safe. An empty, "player", unknown, or drifted tier name resolves to
rank 0 — garbage or a stale tier name can never read as elevation. An empty-named rung is
dropped when the ladder is built, so "" can never resolve to a defined rung.
From verified tier to capability flags
The world never decides your tier; it reads it off a signature-checked session assertion and applies it. The path on a fresh login:
- The world verifies the gate’s signed session assertion offline against the account
service’s public key. Your
loginTieris set only from a signature-checked claim — on a dev/unverified path it’s empty (baseline). - That tier travels into the session (
s.tier). - At the login room, after your persisted flags load,
applyTierFlagsreconciles your reserved flags: it sets each capability flag your tier grants and clears every other reserved flag.
That reconcile-on-every-login is the whole mechanism by which both promotion and demotion take
effect — a since-revoked stale flag is cleared on your next login, and a new grant is set. There
is no live re-tiering in the world; a promote/demote (account/edge-side) lands the next time
you log in. Those gate verbs are themselves staff-only and invisible to a mortal — typing one
returns a plain Huh? with no refusal and no account-service call, gated by a manage_tiers
visibility bit on the session assertion while the account service stays authoritative (see
Accounts & Auth Internals).
Reserved flags and the four-part denylist
Four flags are reserved: holylight, builder, admin, wizinvis. Being reserved buys four
protections, so a capability can only ever come from the trust ladder — never from content, a save
file, or a forged snapshot:
- Content can’t set them. A pack’s
set_flag/clear_flagops refuse reserved flags — a pack can’t grant itself see-all or admin. - They’re never persisted. The character dump omits them.
- They’re not restored from a snapshot. State/handoff restore skips reserved flags, so a forged state or handoff snapshot can’t inject a capability.
- Only login and the staff toggles write them.
applyTierFlags(at login) is their only login-time writer; theholylight/wizinvistoggles are the only others.
Reserved ≠ capability (why wizinvis isn’t grantable)
The reserved set and the capability set differ by exactly one flag: wizinvis. wizinvis
is reserved (content-unsettable, un-persisted, cleared at login) but not tier-grantable — it’s
a staff toggle, not something a tier confers. applyTierFlags filters grants through the
capability set, which is derived as “reserved minus wizinvis.” The important consequence: a
future reserved flag defaults to non-capability, i.e. fails closed — a new reserved flag
can’t accidentally become tier-grantable.
For contrast, perception flags like detect_invis / sense_hidden / hidden are deliberately
plain gameplay flags, not reserved — they affect perception only, never harm or authorization,
so content is free to use them.
Rank-comparison rules
Rank drives several checks:
- Command-use gate. To run a staff verb, your rank must be ≥ the verb’s
MinRank(rankStaff= 1, i.e. “any positive rank is staff”). Below that, the verb reads as unknown (see Builder Commands). stattarget gate.statrefuses a target whose rank exceeds yours; equal (yourself) is always allowed, and mobs/items/rooms are baseline rank 0, so always inspectable. You can’t peek at someone more trusted than you.wizinvisconcealment. A wizinvis staffer is hidden from a viewer of strictly lower rank (resolved via the target’s zone ladder). Equal-or-higher ranks see them; a holylight viewer sees everyone (checked first). A mortal’s baseline 0 conceals from no one.holylighton cap. Only a tier that grants holylight may enable the toggle.debuglive re-check. Delivery re-verifies your rank per line, so a mid-session demote stops zone-internal echoes before you even relog.
Elevation across a cross-shard walk
Current behavior: an admin or builder keeps their elevation when they walk between shards. The
account tier rides the signed handoff snapshot (the tier is bound into the snapshot’s signing
input), and at the destination the session adopts that tier and re-derives its reserved flags
via applyTierFlags when the pending session activates — before the arrival “look.” So
holylight/builder/admin carry across the boundary. Two caveats:
wizinvisclears on arrival. Becausewizinvisis a session concealment and never tier-grantable,applyTierFlagsclears it at the destination — a wizinvis staffer arrives visible and triggers the normal “$n arrives.” This is a documented, intended one-time presence flicker across a shard boundary, not a bug.- Elevation survives only on a signed path. A keyless dev/test shard that skips signature verification does not carry a trustworthy tier and fails closed to baseline. (Such deployments are single-shard and never hand off, so this is not a live-fleet concern.)
The flags themselves are not carried in the snapshot (protection #3 above) — the destination re-derives them from the carried, signed tier. Carrying the tier and re-deriving the flags is what keeps this both consistent and forgery-proof.
The direction
The current model is a small reserved-flag capability set keyed off an ordinal ladder. The
intended direction is a fully content-defined, per-command permission model — where a pack can
express which tier (or capability) each command requires, rather than the engine’s fixed
rankStaff gate. A reserved builder-admin subsection here will document that once it lands.
Related: First Admin Setup (granting/revoking, the audit trail), Builder Commands (the verbs these flags unlock), Accounts & Auth Internals (the signed assertion / auth boundary).