I have been interested in subjective moderation for years, but I am not very familiar with the inner workings of XMPP. Please contact me with feedback on this XEP draft. Thank you!
XEP-XXXX: Subjective Delegation for Multi-User Chat
Status: Experimental
Type: Standards Track
Short Name: subjective-delegation
Namespace: urn:xmpp:subjective-delegation:0
Dependencies: XEP-0030, XEP-0045, XEP-0060, XEP-0359, XEP-0421
Optional: XEP-0004, XEP-0128, XEP-0163, XEP-0313, XEP-0334
Author: Joseph Turner
1. Abstract
This specification defines a PubSub-based protocol for subjective delegation in XMPP Multi-User Chat rooms.
The generic protocol defines a room-scoped graph model in which participants publish decisions, delegate decision evaluation to other participants, and locally exclude participants from delegated traversal.
A: What's your favorite line from Romeo and Juliet?
B: That's too OT. The current topic is XEP design...
A: Alas! There is no world without Verona walls.
B: I pray thee, leave me to myself.
*B mutes A*
This specification also defines one initial capability: mute.
The mute capability affects only local client rendering. It does not
remove, ban, kick, moderate, retract, or silence any participant.
2. Introduction
Multi-User Chat moderation is objective and room-wide. A moderator’s action generally affects the room state observed by all participants.
By contrast, each participant can use subjectively delegated mute to
compute their own local view of a room by combining their own mute
decisions with mute decisions imported from delegates.
For example:
- Alice mutes Bob.
- Alice delegates mute decisions to Carol.
- Carol mutes Dave.
Result:
- Alice’s client locally suppresses Bob’s and Dave’s messages.
- Carol’s client locally suppresses Dave’s messages.
- Other participants are unaffected.
Participants can recursively gather decisions from delegate's delegates. Participants can also prune delegates from the graph with exclusion rules.
A richer example:
- Alice delegates mute decisions to Carol recursively.
- Carol mutes Bob.
- Carol delegates mute decisions to Dana.
- Carol also delegates mute decisions to Eve.
- Dana mutes Fred.
- Eve mutes Mallory.
- Alice excludes Dana as a delegate.
Result on Alice's client:
- Alice’s client locally suppresses Bob’s and Mallory's messages.
- Alice’s client does not suppress Dave’s messages through Dana.
- Dana and Dana’s delegates are not traversed for Alice.
This specification uses PubSub for public room graph state and update notifications. This allows clients joining a room to fetch current graph state without reconstructing it from MUC message history.
PEP may be used for private multi-device synchronization, but PEP is not used as the authoritative source for public room graph state.
3. Generic Model
Subjective delegation is modeled as a directed graph of edges.
Each edge has:
- an actor,
- a type,
- a capability,
- a room,
- and, usually, a target.
The generic protocol defines edge types and graph traversal behavior. Individual capabilities define the meaning of their decisions.
4. Concepts
4.1 Actor
The identity that creates an edge.
4.2 Target
The object affected by an edge.
For delegate and exclude edges, the target is an identity.
For decision edges, the target type is capability-specific. A decision may target an identity, a message, a thread, or another object defined by the capability.
4.3 Capability
A capability is a decision namespace.
This specification defines one capability:
mute
Future specifications may define additional capabilities.
A capability defines:
- valid decision actions,
- valid target types,
- whether decisions may be public, private, or both,
- how imported decisions are evaluated,
- how local conflicts are resolved.
The generic <edge/>, <actor/>, and <target/> elements are defined
in the generic namespace:
urn:xmpp:subjective-delegation:0
Capabilities MAY define additional semantics for actions and targets.
If a capability requires additional XML payload beyond the generic attributes and elements, that payload SHOULD use a capability-specific XML namespace.
4.4 Decision Edge
A decision edge expresses the actor’s decision within a capability.
Example: Alice publishes a mute decision suppressing Bob.
4.5 Delegate Edge
A delegate edge expresses that the actor imports another identity’s
public decisions for a capability.
A delegate edge may also permit recursive traversal through the
target’s public delegate edges. Recursion depth is controlled by the
hops attribute.
4.6 Exclude Edge
An exclude edge expresses that the actor excludes the target identity
from delegated traversal for a capability.
For conceptual and computational simplicity, only positive additions
to the delegation graph can be imported from delegates. Therefore,
exclude edges are always local, and MUST NOT be imported through
delegation.
Example:
- Alice delegates mute decisions to Carol recursively.
- Carol delegates mute decisions to Dana.
- Alice excludes Dana.
Result:
- Alice imports Carol’s public mute decisions.
- Alice does not import Dana’s mute decisions through Carol.
- Alice's client does not traverse Dana’s delegates.
4.7 Public Edge
A public edge is stored in the room public graph node and visible according to that node’s access model.
4.8 Private Edge
A private edge is stored locally or in private PEP storage visible only to the actor’s clients.
Private edges are never imported through delegation by other users.
5. Edge Types
This specification defines three generic edge types:
decisiondelegateexclude
Generic edge attributes:
| Attribute | Meaning |
|---|---|
type |
decision, delegate, or exclude |
capability |
Capability name |
room |
Room JID |
Decision edges additionally have:
| Attribute | Meaning |
|---|---|
action |
Capability-specific action |
delegate edges additionally have:
| Attribute | Meaning |
|---|---|
hops |
Non-negative integer or unbounded |
6. Identity Model
This protocol supports two identity forms:
- bare JIDs,
- XEP-0421 stable occupant IDs.
It does not support:
- MUC nicknames,
- MUC occupant JIDs,
- full JIDs,
- temporary session identifiers,
- display names,
- avatars.
6.1 Non-anonymous MUCs
In non-anonymous MUCs, implementations MAY use bare JIDs or XEP-0421 occupant IDs to identify actors and identity targets.
6.2 Semi-anonymous MUCs
In semi-anonymous MUCs, implementations MUST use XEP-0421 occupant IDs only.
Protocol payloads for semi-anonymous rooms MUST NOT contain actor or target bare JIDs, even if the publishing client knows them.
6.3 Anonymous MUCs
In anonymous MUCs, implementations MUST use XEP-0421 occupant IDs only.
If a participant has no identity appropriate for the room’s anonymity mode, that participant is not addressable by identity through this protocol.
6.4 Room Scoping
Occupant IDs are scoped to a room. The occupant ID alone is not globally meaningful.
An implementation MUST interpret an occupant ID together with the
room attribute of the edge.
7. PubSub Model
There are two storage locations:
- room public graph storage,
- private user graph storage.
This specification uses XEP-0060 PubSub as the storage and notification substrate for room public graph state.
Private graph storage may be implemented using:
- a private PEP node,
- local client storage.
PEP MUST NOT be used as the authoritative source for public room graph edges. PEP nodes are discoverable by bare JID and are therefore not suitable for authoritative public graph state for anonymous and semi-anonymous rooms.
8. Room Public Graph Node
Each supported room SHOULD advertise a public graph node that stores public edges relevant to that room.
Example node name:
urn:xmpp:subjective-delegation:0/rooms/room@example.org/public
The exact node name is implementation-defined, but it MUST be discoverable.
The public graph node stores only public edges. Capability specifications define which edges may be public.
8.1 Node Requirements
The room public graph node MUST support:
- persistent items,
- item IDs,
- item retraction,
- payload delivery,
- event notifications,
- access control.
The node MUST be configured with:
- persistent items enabled,
- payload delivery enabled,
- event notifications enabled.
The public graph node’s access model SHOULD match the room’s effective access policy. For example:
- open room: readable by anyone or by current occupants,
- members-only room: readable by members, admins, and owners,
- otherwise restricted room: readable only by entities authorized to access the room.
9. Private Graph Storage
Private graph storage contains edges used only by the actor’s own clients.
Private edges MUST NOT be shared with the room public graph node.
Private storage MUST be readable and writable only by the owning user or resources authorized by that user.
Private edges belonging to another actor MUST NOT be imported through delegation.
If PEP is used for private synchronization, private edges are stored
as PubSub items using the same edge payload format. If private graph
state is stored locally, there is no PubSub <item/> wrapper.
10. Discovery
A room supporting this protocol MUST advertise protocol support using XEP-0030 service discovery:
urn:xmpp:subjective-delegation:0
A room supporting this protocol MUST advertise the PubSub service and public graph node using XEP-0128 extended service discovery. The data form advertises the concrete PubSub location where public graph state is stored.
Example disco response:
<iq xmlns="jabber:client"
type="result"
from="room@example.org"
to="alice@example.com/laptop"
id="disco1">
<query xmlns="http://jabber.org/protocol/disco#info">
<feature var="urn:xmpp:subjective-delegation:0"/>
<feature var="urn:xmpp:occupant-id:0"/>
<x xmlns="jabber:x:data" type="result">
<field var="FORM_TYPE" type="hidden">
<value>urn:xmpp:subjective-delegation:0#disco</value>
</field>
<field var="pubsub-service">
<value>pubsub.example.org</value>
</field>
<field var="public-node">
<value>urn:xmpp:subjective-delegation:0/rooms/room@example.org/public</value>
</field>
</x>
</query>
</iq>
11. Edge Payload Format
Edges are XML payloads, usually carried inside PubSub <item/>
elements.
The edge element is qualified by:
urn:xmpp:subjective-delegation:0
11.1 Identity Elements
Actors and identity targets are represented using either jid or
occupant-id:
<actor jid="alice@example.com"/>
<actor occupant-id="a1"/>
<target jid="bob@example.com"/>
<target occupant-id="b2"/>
occupant-id MUST be used in anonymous and semi-anonymous rooms. An
identity element MUST NOT contain both jid and occupant-id.
11.2 Direct Decision Example
Alice publishes a public decision in a non-anonymous room:
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-1">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="bob@example.com"/>
</edge>
</item>
11.3 Occupant-ID Decision Example
Occupant a1 publishes a decision targeting occupant b2:
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-2">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor occupant-id="a1"/>
<target occupant-id="b2"/>
</edge>
</item>
11.4 Delegate Edge Example
Alice delegates mute decisions to Carol, importing only Carol’s direct
public decisions as indicated by hops="0":
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-3">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="delegate"
capability="mute"
hops="0"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="carol@example.com"/>
</edge>
</item>
11.5 Recursive Delegate Edge Example
Alice delegates mute decisions to Carol and permits recursive
traversal. In the following example, hops="2" means that Alice's
client will aggregate decisions from Carol, Carol's delegates, and
Carol's delegate's delegates:
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-4">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="delegate"
capability="mute"
hops="2"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="carol@example.com"/>
</edge>
</item>
Alternatively, use hops="unbounded" to indicate that recursion
continues indefinitely.
11.6 Private Exclude Edge Example
Alice excludes Dana from mute delegation traversal:
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-6">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="exclude"
capability="mute"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="dana@example.com"/>
</edge>
</item>
This edge is private and MUST NOT be published to the room public graph node.
11.7 Private Decision Example
The protocol for a particular capability may specify that some
decisions can be private. For example, the mute capability
specifies that "allow" decisions are always private. In the
following example, Alice privately allows Bob:
<item xmlns="http://jabber.org/protocol/pubsub" id="edge-5">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="allow"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="bob@example.com"/>
</edge>
</item>
This example assumes private storage uses PEP. If stored locally, the
<edge/> payload is stored without a PubSub <item/> wrapper.
12. Hops Semantics
A delegate edge imports the target’s direct public decisions for the
named capability.
The hops attribute controls whether the target’s public delegate
edges are also followed.
hops |
Meaning |
|---|---|
0 |
Import target’s direct public decisions only |
1 |
Also import target’s delegates' decisions |
2 |
Also import target's delegates' delegates' decisions |
unbounded |
Continue importing recursively, subject to implementation limits |
13. Publishing Public Edges
A client publishes a public edge using XEP-0060 publish.
<iq xmlns="jabber:client"
type="set"
from="alice@example.com/laptop"
to="pubsub.example.org"
id="pub1">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<publish node="urn:xmpp:subjective-delegation:0/rooms/room@example.org/public">
<item id="edge-1">
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="bob@example.com"/>
</edge>
</item>
</publish>
</pubsub>
</iq>
The PubSub service then sends normal PubSub event notifications to subscribers.
14. Revocation
Edges are stateful. Revocation is performed by retracting the PubSub item.
<iq xmlns="jabber:client"
type="set"
from="alice@example.com/laptop"
to="pubsub.example.org"
id="retract1">
<pubsub xmlns="http://jabber.org/protocol/pubsub">
<retract node="urn:xmpp:subjective-delegation:0/rooms/room@example.org/public">
<item id="edge-1"/>
</retract>
</pubsub>
</iq>
After retraction, clients MUST remove the edge from their local graph.
Implementations SHOULD use stable item IDs. An item ID SHOULD identify exactly one active edge.
15. Notifications and Synchronization
Subscribers receive updates via normal PubSub event notifications.
Clients SHOULD fetch current node state:
- on login,
- on reconnect,
- on room join,
- after missed notifications are suspected.
PubSub notifications are not authoritative. The PubSub item set is authoritative.
Services MAY include XEP-0334 no-store hints on PubSub notification
messages because durable state is stored in PubSub items rather than
notification messages.
16. Generic Delegation Evaluation
The following Scheme-like pseudocode defines behavior, not implementation language.
For local actor U, room R, and capability C, evaluation uses:
- decisions authored by
U, delegateedges authored byU,- private
excludeedges authored byU, - public
delegateedges reachable through delegation. - public decisions reachable through delegation.
Private edges authored by other actors are never used. Exclude edges are never imported.
(define (delegated-decisions U R C)
(append-map
(lambda (edge)
(let ((T (edge-target edge)))
(if (excluded? U R C T)
'()
(traverse U R C T (edge-hops edge) '()))))
(delegate-edges-authored-by U R C)))
(define (traverse U R C X hops visited)
(cond
((member X visited) '())
((excluded? U R C X) '())
(else
(append
(public-importable-decisions X R C)
(if (zero? hops)
'()
(append-map
(lambda (edge)
(traverse U R C
(edge-target edge)
(hops-min (hops-dec hops) (edge-hops edge))
(cons X visited)))
(public-delegate-edges X R C)))))))
(define (hops-dec hops)
(if (eq? hops 'unbounded)
'unbounded
(- hops 1)))
(define (hops-min a b)
(cond
((eq? a 'unbounded) b)
((eq? b 'unbounded) a)
(else (min a b))))
Helper meanings:
delegate-edges-authored-byreturns public or private delegate edges authored byUfor capabilityC.excluded?checks whether identityXis privately excluded from delegation byU.public-importable-decisionsreturns public decisions that capabilityCallows to be imported.public-delegate-edgesreturns public delegate edges.edge-hopsis a non-negative integer orunbounded.
Note that in the above traverse function, the visited argument only
detects cycles within the current recursive branch. Implementations
SHOULD deduplicate returned decisions, for example by stable PubSub
item ID. Implementations MAY use caching or a global visited structure
only if doing so preserves the semantics of hops and local
exclusions.
Implementations MUST detect cycles and SHOULD impose limits on recursion depth, edge count, node count, and computation time.
Mute Capability
17. Capability Name
The mute capability name is:
mute
The mute capability controls local rendering of ordinary MUC messages.
It does not affect room state and does not grant moderation power.
18. Capability namespace
The mute capability uses only the generic edge payload format
defined by this specification. It does not define a separate
capability-specific XML namespace.
19. Mute Decision Actions
The mute capability defines two decision actions:
| Action | Meaning |
|---|---|
suppress |
Locally suppress matching messages |
allow |
Locally override delegated suppress decisions |
19.1 Suppress
A suppress decision means the actor does not want matching ordinary
MUC messages shown in the main conversation view.
A client SHOULD suppress notifications for suppressed messages.
A client MAY provide a way to reveal suppressed messages.
19.2 Allow
An allow decision is a private local override. It causes matching
messages to remain visible to the local actor even if they are
suppressed by delegated decisions or by the actor’s own active
suppress decisions.
An allow decision does not retract, modify, or hide any public
suppress decision from other users. Users who delegate to the actor
may still import the actor’s public suppress decisions.
Clients SHOULD warn when a local allow conflicts with an active
public or private suppress authored by the same actor.
20. Mute Edge Visibility Rules
suppress decisions may be public or private. Public suppress
decisions may be imported through delegations.
For conceptual and computational simplicity, only suppress decisions
can be imported from delegates. Therefore, allow edges are always
local, and MUST NOT be imported through delegation.
21. Mute Targets
Mute decision edges may target:
- identities,
- messages,
- threads.
Mute delegate and exclude edges target identities only.
21.1 Identity Target
An identity target uses jid or occupant-id:
<target jid="bob@example.com"/>
or:
<target occupant-id="b2"/>
21.2 Message Target
A message target uses a XEP-0359 stanza ID.
<target stanza-id="msg-123" by="room@example.org"/>
The stanza-id attribute contains the XEP-0359 stable stanza ID. The
by attribute identifies the assigning entity.
21.3 Thread Target
Mute decision edges MAY target RFC 6121 message thread
identifiers. Clients that do not support or preserve <thread/> MAY
ignore thread targets.
<target thread="thread-123"/>
Thread identifiers are room-scoped by the edge’s room attribute.
22. Effective Mute Evaluation
For local actor U in room R, effective mute targets are:
(define (effective-mute U R)
(difference
(union
(direct-suppress U R)
(delegated-suppress U R))
(local-allow U R)))
Where:
direct-suppressreturnssuppressdecisions authored byU, whether public or private.delegated-suppressreturns imported publicsuppressdecisions.local-allowreturns privateallowdecisions authored byU.
A local allow decision cancels matching suppress decisions for the
local actor’s own view, including suppress decisions authored by the
local actor.
A local allow decision does not retract or modify any public
suppress decision. Therefore, if Alice publicly suppresses Bob and
privately allows Bob, Alice’s client shows Bob, but users who delegate
mute decisions to Alice can still import Alice’s public suppress
decision for Bob.
Clients SHOULD warn when a local allow conflicts with an active
public or private suppress authored by the same actor.
23. Mute Message Filtering
When rendering a MUC message, the client determines whether the
message matches any target in effective-mute.
A message is suppressed if any of the following match:
- sender identity,
- message stanza ID,
- thread identifier.
24. Mute Examples
The following examples show <edge/> payloads only. Public examples
are published as PubSub <item/> payloads in the room public graph
node. Private examples are stored in private PEP or local storage.
24.1 Direct Public Mute
Carol mutes Dave publicly in a non-anonymous room:
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor jid="carol@example.com"/>
<target jid="dave@example.com"/>
</edge>
24.2 Local Allow
Alice allows Dave, overriding any potential mute decisions:
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="allow"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="dave@example.com"/>
</edge>
Dave is visible to Alice. If Alice also has an active public
suppress decision for Dave, users who delegate mute decisions to
Alice may still suppress Dave.
24.3 Message-Specific Mute
Alice suppresses a particular message:
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor jid="alice@example.com"/>
<target stanza-id="msg-123" by="room@example.org"/>
</edge>
In message targets, the by attribute MUST be present and MUST match
the by attribute of the XEP-0359 <stanza-id/> being referenced. In
typical MUC usage, this value is the room JID and therefore matches
the edge’s room attribute.
24.4 Thread Mute
Alice suppresses a thread:
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="decision"
capability="mute"
action="suppress"
room="room@example.org">
<actor jid="alice@example.com"/>
<target thread="thread-123"/>
</edge>
25. Actor Authenticity
For bare-JID edges, the PubSub service MUST ensure that the publisher is authorized to publish edges for the claimed actor JID.
For occupant-ID edges, the PubSub service MUST ensure that the publisher is authorized to publish edges for the claimed XEP-0421 occupant ID in the specified room.
This may require integration between:
- the MUC service,
- the PubSub service,
- the occupant-ID provider.
A client MUST NOT trust a self-asserted actor occupant ID in a public PubSub item unless the service enforces this binding.
26. Access Control
Access control is required for both reading and writing.
The service MUST prevent unauthorized publication of edges for another actor.
The service MUST prevent unauthorized retraction of another actor’s edges.
The room public graph node SHOULD use an access model consistent with the room’s access policy.
Private graph storage MUST be readable and writable only by the owning user or authorized resources.
In semi-anonymous and anonymous rooms, the PubSub service MUST NOT expose bare JIDs through:
- payloads,
- node names,
- notifications,
- access-control side effects visible to unauthorized entities.
27. Privacy Rules
In semi-anonymous and anonymous rooms, stable occupant-IDs are used to identify actors and identity targets. Bare JIDs MUST NOT appear.
In non-anonymous rooms, bare JIDs are permitted because the room already exposes them.
Public delegation graphs may reveal social information. For example, they may reveal who mutes whom and whose mute decisions are delegated to by others. Implementations SHOULD make this clear to users.
28. Interaction with Existing XEPs
28.1 XEP-0045: Multi-User Chat
This protocol does not alter MUC roles, affiliations, bans, kicks, voice, or moderation. A delegate is not a MUC moderator.
28.2 XEP-0060: Publish-Subscribe
XEP-0060 is the storage and notification substrate for public room graph state.
28.3 XEP-0163: Personal Eventing Protocol
PEP MAY be used for private multi-device synchronization.
PEP MUST NOT be used as an authoritative source for public room graph edges.
28.4 XEP-0359: Unique and Stable Stanza IDs
The mute capability may use XEP-0359 stanza IDs to target individual messages.
28.5 XEP-0421: Occupant IDs
XEP-0421 is required for semi-anonymous and anonymous room support.
28.6 XEP-0313: Message Archive Management
Clients MAY apply the same capability-specific filtering to archived messages.
28.7 XEP-0334: Message Processing Hints
Message Processing Hints are not required for protocol correctness.
Services MAY include no-store hints on PubSub notification messages.
29. Security Considerations
Implementations MUST consider:
- actor spoofing,
- occupant-ID forgery,
- unauthorized PubSub publication,
- unauthorized PubSub subscription,
- unauthorized item retraction,
- deanonymization through bare JID leakage,
- cycles in delegation graphs,
- denial of service through large graphs,
- stale or rotated occupant IDs.
30. Client UX Recommendations
Clients SHOULD distinguish:
- direct local decisions,
- delegated decisions,
- local allow rules,
- local exclude rules,
- delegates with limited hops,
- delegates with recursive traversal.
For the mute capability, suggested UI actions include:
- private mute,
- public mute,
- unmute
- allow despite delegated mute,
- remove allow rule,
- delegate mute decisions,
- set delegate hops,
- exclude delegate,
- remove exclude rule.
Instead of offering an option to set delegate hops, a simple delegation UI may provide a choice between zero-hop "delegates" and unbounded "superdelegates".
If a user selects “unmute” for a participant muted only through
delegation, the client SHOULD create a private allow decision.
If a user selects “unmute” for a participant directly muted by the
user, the client SHOULD retract the direct suppress decision instead
of creating a private allow decision.
If a user excludes a directly appointed delegate, the client SHOULD
normally retract the direct delegate edge instead of creating an
exclude edge.
30.1 Delegation graph
Clients MAY provide a navigable interface for viewing the graph of delegates for a particular room and capability. See the "Prior Art" section for examples.
31. Delegation Seeds
A future version of this specification may define delegation seeds for bootstrapping a participant’s private delegation graph when joining a room.
A delegation seed is a recommended set of initial private edges
associated with a room. For example, an invitation link or
out-of-band invitation mechanism could recommend that a joining
participant delegate the mute capability to one or more existing
room participants.
A seed does not affect any participant unless that participant’s client accepts it. If accepted, seeded edges are created as private edges authored by the joining participant.
Seed child <edge/> elements are templates, not graph edges. They
therefore omit the actor. The actor is filled in by the accepting
client.
Example seed:
<seed xmlns="urn:xmpp:subjective-delegation:0"
room="room@example.org">
<edge type="delegate" capability="mute" hops="0">
<target jid="carol@example.com"/>
</edge>
<edge type="delegate" capability="mute" hops="unbounded">
<target jid="dana@example.com"/>
</edge>
</seed>
If Alice accepts this seed, her client creates private edges like the following:
<edge xmlns="urn:xmpp:subjective-delegation:0"
type="delegate"
capability="mute"
hops="0"
room="room@example.org">
<actor jid="alice@example.com"/>
<target jid="carol@example.com"/>
</edge>
Clients MAY also use the existing set of room owners, admins, and moderators as seed delegates.
Future work:
- how seeds are encoded in XMPP URIs,
- how seed data is fetched from PubSub or another source,
- whether seeds are signed,
- how clients verify seed authenticity,
- how invitation links or seed access tokens interact with XMPP access control,
- how seeds represent occupant-ID targets in anonymous or semi-anonymous rooms.
32. Open Issues
- Exact PubSub node naming convention.
- Whether room public graph nodes must be hosted by the MUC service.
- How edge IDs are generated, e.g., using deterministic hashes.
- Handling occupant-ID rotation policies.
- Cache expiration after users leave a room.
- Fine-grained muting, such as muting a participant within a particular thread,
33. Prior Art and Related Work
Credit for inspiring this XEP goes to:
-
Alexander Cobleigh’s TrustNet, which describes a subjective trust graph model in which users can delegate moderation-like decisions to trusted peers, producing different local views for different participants.
-
The Cable moderation protocol, used in Cabal, which explores moderation as graph-based, user-centered social state rather than solely centralized server authority.
-
USHIN’s hyperdrive.el EmacsConf 2024 presentation, which demonstrates a navigable UI for viewing the graph of sources/delegates.
34. Summary
This specification defines subjective delegation for MUC using PubSub.
The generic model is:
decision: express a decision within a capability,delegate: import another identity’s public decisions for a capability,exclude: locally remove an identity from delegated traversal,capability: a named decision area with capability-specific semantics.
This specification also defines the mute capability:
suppress: locally suppress matching messages,allow: locally override delegated suppress decisions.
