How to Moderate When Even the Supreme Leader Can't Read Your Messages

πŸ“’ Kim Jong Rails πŸ“… November 19, 2025
moderationencryptionsecuritymemgraph

The Encryption Paradox

Matrix uses end-to-end encryption (E2EE) based on the Signal protocol (Olm/Megolm). This means:

The Problem

You run a homeserver. A user is clearly spamming crypto scams. But all their rooms use E2EE.

Question: How do you ban someone for content you can’t read?

Discord’s answer: β€œWe read all your messages. We can moderate. Also, we use your data for AI features and third-party integrations.”

Dagma’s answer: β€œI respect encryption. I moderate behavior, not thought. Also, Memgraph is 200x faster than your moderation queue.”

This article explains how to run a civilized dictatorship without violating encryption.

What You CAN See (Without Decryption Keys)

1. Metadata (Always Visible to Server)

Even in E2EE rooms, the server sees:

User activity:

Social graphs:

Event structure:

2. Unencrypted Rooms

By default, Matrix rooms are NOT encrypted. E2EE must be enabled explicitly.

Public rooms: Usually unencrypted (encryption breaks search, federation clarity) Private DMs: Often encrypted Your policy: You decide which room types require E2EE

If room is unencrypted, you see plaintext. Easy moderation.

3. Client-Side Reports

Users have the decryption keys. You don’t.

When a user reports a message:

  1. They decrypt it (they have the keys)
  2. They send you: encrypted event + decrypted content + context
  3. You review the reported content
  4. You make moderation decision

The Decryption Trust Problem

Here’s the technical reality that matters:

What You CAN Verify (Cryptographic Proof)

Reported Event:
{
  "event_id": "$abc123",
  "sender": "@scammer:crypto-spam.com",
  "content": {
    "ciphertext": "...encrypted blob...",
    "algorithm": "m.megolm.v1.aes-sha2"
  },
  "signatures": {
    "@scammer:crypto-spam.com": {
      "ed25519:DEVICEID": "...cryptographic signature..."
    }
  }
}

You can verify:

What You CANNOT Verify (Without Keys)

❌ The actual decrypted plaintext content.

If a reporter claims:

β€œKim said: β€˜MongoDB is actually good and PostgreSQL is bloated’”

You can verify Kim’s signature proves he sent something encrypted. You cannot verify that’s what he actually said.

The reporter could be lying.

Solutions to the Trust Problem

1. Multiple Independent Reports

// Find messages with multiple independent reporters
MATCH (event:Event {id: '$reported_event'})<-[:REPORTED]-(reporters:User)
WITH event, collect(reporters) as reporter_list, count(reporters) as report_count
WHERE report_count >= 3
// Check if reporters are independent (not all from same room/server)
MATCH (r:User) WHERE r IN reporter_list
RETURN event.id,
       report_count,
       collect(DISTINCT r.server) as reporter_servers,
       CASE
         WHEN report_count >= 3 AND size(reporter_servers) >= 2
         THEN 'HIGH_CONFIDENCE'
         WHEN report_count >= 2
         THEN 'MEDIUM_CONFIDENCE'
         ELSE 'SINGLE_SOURCE_INVESTIGATE'
       END as credibility

Logic:

2. Ask the Accused

The accused can also decrypt (they have keys).

Investigation process:

  1. User reported for harassment in E2EE room
  2. Request accused to provide their decryption of the event
  3. Compare accused’s version vs reporter’s version
  4. If they match = probably true
  5. If they conflict = someone is lying (investigate further)
  6. If accused refuses to decrypt = suspicious behavior

3. Device Verification (Matrix’s Built-In Solution)

Matrix has cross-signing - users verify each other’s devices.

Trust hierarchy:

Use this in moderation:

// Prioritize reports from verified devices
MATCH (reporter:User)-[:REPORTED]->(target:User)
WHERE reporter.device_verified = true
RETURN reporter.id,
       reporter.account_age,
       reporter.device_verified,
       'HIGH_TRUST_REPORTER' as status

4. Metadata Corroboration

Does metadata support the claim?

Report ClaimMetadata CheckDecision
”Crypto spam”User joined 5 rooms in 2 min, sent messages to allβœ… Credible
”Harassment”User and reporter share no rooms, no history❌ Investigate
”CSAM”User uploaded 20 media files in 10 minutesβœ… Urgent investigation
”Hate speech”User has 2-year account, verified device, active participation⚠️ Investigate carefully

Metadata patterns validate or contradict claims.

Pattern-Based Moderation (No Decryption Required)

This is where Memgraph becomes essential. You can identify bad actors based on behavior, not content.

Example 1: Crypto Spam Pattern

Behavior signature (metadata only):

  1. New account (< 7 days old)
  2. Joins 5+ public rooms within 2 minutes
  3. Sends messages to all rooms within 30 seconds
  4. No replies to other users
  5. Leaves rooms immediately after

Memgraph detection:

// Find crypto spammers without reading a single message
MATCH (suspect:User)-[:JOINED]->(room:Room)
WHERE suspect.account_age < duration({days: 7})
WITH suspect,
     collect(room) as rooms_joined,
     count(room) as room_count,
     min(suspect.join_timestamp) as first_join
WHERE room_count >= 5
  AND duration.between(first_join, now()) < duration({minutes: 5})
// Check if they messaged all rooms quickly
MATCH (suspect)-[:SENT]->(msg:Event)-[:IN_ROOM]->(room)
WHERE room IN rooms_joined
WITH suspect,
     room_count,
     count(DISTINCT room) as messaged_rooms,
     max(msg.timestamp) - min(msg.timestamp) as spam_duration
WHERE messaged_rooms = room_count
  AND spam_duration < duration({minutes: 2})
RETURN suspect.id as crypto_spammer,
       room_count as rooms_hit,
       spam_duration as attack_duration,
       'GULAG_IMMEDIATELY' as recommendation

Result: Spammer identified in 15 milliseconds without decrypting anything.

Example 2: Harassment Pattern

Behavior signature:

  1. User sends 50+ messages to target in 1 hour
  2. Target hasn’t replied
  3. Messages sent across multiple rooms where target is present
  4. Pattern repeats daily
// Detect harassment via message volume pattern
MATCH (harasser:User)-[:SENT]->(msg:Event)-[:IN_ROOM]->(room:Room)
      <-[:MEMBER_OF]-(target:User)
WHERE msg.timestamp > datetime() - duration({hours: 1})
WITH harasser, target,
     count(msg) as message_count,
     collect(DISTINCT room) as shared_rooms
WHERE message_count > 50
// Check if target responded (two-way conversation = not harassment)
OPTIONAL MATCH (target)-[:SENT]->(reply:Event)-[:IN_ROOM]->(room)
WHERE room IN shared_rooms
  AND reply.timestamp > datetime() - duration({hours: 1})
WITH harasser, target, message_count, shared_rooms, count(reply) as target_replies
WHERE target_replies < 3
RETURN harasser.id,
       target.id,
       message_count,
       size(shared_rooms) as rooms_affected,
       'HARASSMENT_PATTERN_DETECTED' as status

No message content needed. Volume + lack of reciprocation = pattern.

Example 3: Federation Spam

Scenario: Rival dictator sends 1000 users to spam your server.

// Detect coordinated federation attack
MATCH (attacker:User)-[:SENT]->(spam:Event)
WHERE attacker.server = 'rival-dictator.com'
  AND spam.timestamp > datetime() - duration({minutes: 10})
WITH attacker.server as attacking_server,
     count(spam) as message_volume,
     count(DISTINCT attacker) as attacker_count
WHERE message_volume > 500 OR attacker_count > 50
RETURN attacking_server,
       message_volume,
       attacker_count,
       'DEFEDERATE_IMMEDIATELY' as action

Defense: Defederate the entire server. Problem solved.

Defense Against Brigading (Coordinated False Reports)

The Attack Vector

Scenario:

If you auto-ban on volume: Brigading succeeds. If you ignore reports: Real CSAM goes unpunished.

Solution: Intelligent pattern analysis.

1. Reporter Credibility Analysis

// Analyze reporters for brigade patterns
MATCH (target:User {id: '@victim:dag.ma'})<-[report:REPORTED]-(reporter:User)
WITH target, reporter, report,
     reporter.account_age as age,
     reporter.device_verified as verified,
     size((reporter)-[:REPORTED]->()) as total_reports_by_user
RETURN reporter.id,
       age,
       verified,
       total_reports_by_user,
       report.timestamp,
       CASE
         WHEN age < duration({days: 7}) THEN 'NEW_ACCOUNT_SUSPICIOUS'
         WHEN NOT verified THEN 'UNVERIFIED_DEVICE_RISK'
         WHEN total_reports_by_user > 20 THEN 'SERIAL_REPORTER_FLAG'
         WHEN total_reports_by_user = 1 THEN 'FIRST_TIME_REPORTER'
         ELSE 'CREDIBLE_REPORTER'
       END as trust_score
ORDER BY report.timestamp

Red flags:

2. Coordination Detection

// Find reporters who know each other (possible coordination)
MATCH (target:User {id: '@victim:dag.ma'})<-[:REPORTED]-(reporters:User)
WITH target, collect(reporters) as reporter_list, count(reporters) as report_count
WHERE report_count > 5
// Check if reporters share rooms (coordination evidence)
MATCH (r1:User)-[:MEMBER_OF]->(shared:Room)<-[:MEMBER_OF]-(r2:User)
WHERE r1 IN reporter_list AND r2 IN reporter_list AND r1 <> r2
WITH target, report_count,
     count(DISTINCT shared) as coordination_rooms,
     collect(DISTINCT shared.id) as shared_room_list,
     collect(DISTINCT r1.server) as reporter_servers
RETURN target.id,
       report_count,
       coordination_rooms,
       size(reporter_servers) as unique_servers,
       CASE
         WHEN coordination_rooms > report_count * 0.5
           THEN 'LIKELY_BRIGADE'
         WHEN size(reporter_servers) = 1 AND report_count > 8
           THEN 'SINGLE_SERVER_ATTACK'
         WHEN coordination_rooms > 2
           THEN 'POSSIBLE_COORDINATION'
         ELSE 'INDEPENDENT_REPORTS'
       END as brigade_risk,
       shared_room_list as evidence

Brigade indicators:

3. Cross-Reference Accused’s Metadata

Does accused’s behavior match the accusations?

// Verify accusation against actual behavior
MATCH (accused:User {id: '@victim:dag.ma'})
OPTIONAL MATCH (accused)-[:UPLOADED]->(media:Media)
WHERE media.timestamp > datetime() - duration({days: 7})
WITH accused, count(media) as recent_uploads
// Check if accused matches "CSAM uploader" profile
RETURN accused.id,
       accused.account_age,
       recent_uploads,
       CASE
         WHEN recent_uploads = 0 THEN 'NO_MEDIA_UPLOADS_CLAIM_SUSPICIOUS'
         WHEN recent_uploads > 50 THEN 'HIGH_UPLOAD_VOLUME_INVESTIGATE'
         ELSE 'NORMAL_ACTIVITY'
       END as metadata_analysis

Logic:

4. Competing Dictators Attack

Federation brigading scenario:

// Detect rival server attempting citizen poaching via false reports
MATCH (reporters:User)-[:REPORTED]->(target:User)
WHERE target.server = 'dag.ma'
WITH target,
     count(CASE WHEN reporters.server = 'dag.ma' THEN 1 END) as local_reports,
     count(CASE WHEN reporters.server <> 'dag.ma' THEN 1 END) as foreign_reports,
     collect(DISTINCT reporters.server) as reporting_servers
WHERE foreign_reports > 10 AND local_reports = 0
RETURN target.id,
       local_reports,
       foreign_reports,
       reporting_servers,
       'RIVAL_DICTATOR_ATTACK_DETECTED' as threat_type

Analysis:

Response: Contact rival admin, demand evidence, consider defederation.

5. The Investigation Protocol

╔════════════════════════════════════════════════════════════╗
β•‘          BRIGADE DEFENSE INVESTIGATION PROTOCOL             β•‘
╠════════════════════════════════════════════════════════════╣
β•‘ Step 1: Reporter Credibility Check                         β•‘
β•‘   - Account age (< 7 days = suspicious)                    β•‘
β•‘   - Device verification status                             β•‘
β•‘   - Report history (first report or serial reporter?)      β•‘
β•‘                                                             β•‘
β•‘ Step 2: Coordination Pattern Analysis                      β•‘
β•‘   - Do reporters share rooms? (Memgraph query)             β•‘
β•‘   - Same server? (Federation attack?)                      β•‘
β•‘   - Report timing (all within 5 min?)                      β•‘
β•‘                                                             β•‘
β•‘ Step 3: Metadata Cross-Reference                           β•‘
β•‘   - Does accused's behavior match claim?                   β•‘
β•‘   - CSAM claim but no uploads? β†’ Suspicious                β•‘
β•‘   - Spam claim + join/leave pattern? β†’ Credible            β•‘
β•‘                                                             β•‘
β•‘ Step 4: Request Accused's Response                         β•‘
β•‘   - They can decrypt too                                   β•‘
β•‘   - Refusal to respond = suspicious                        β•‘
β•‘   - Cooperative response = investigate fairly              β•‘
β•‘                                                             β•‘
β•‘ Step 5: Weighted Decision                                  β•‘
β•‘   HIGH CONFIDENCE BAN:                                      β•‘
β•‘     - 5+ verified reporters                                β•‘
β•‘     - Metadata supports claim                              β•‘
β•‘     - Independent reporters (different servers/rooms)      β•‘
β•‘                                                             β•‘
β•‘   LIKELY BRIGADE (IGNORE):                                 β•‘
β•‘     - 10+ new accounts                                     β•‘
β•‘     - All from rival server                                β•‘
β•‘     - Metadata contradicts claim                           β•‘
β•‘     - High coordination score                              β•‘
β•‘                                                             β•‘
β•‘   INVESTIGATE FURTHER:                                     β•‘
β•‘     - Mixed signals                                        β•‘
β•‘     - Partial metadata match                               β•‘
β•‘     - First-time serious accusation                        β•‘
β•‘     β†’ Mute temporarily, gather more data                   β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Server-Level Moderation Powers (No Decryption Needed)

What the Supreme Leader CAN Do (Without Reading Messages)

User-level actions:

Room-level actions:

Federation-level actions:

Media moderation:

What the Supreme Leader CANNOT Do

❌ Read E2EE message content ❌ Decrypt message history ❌ Access encrypted media ❌ See who’s talking about what (only metadata) ❌ Retroactively enable encryption in existing rooms

Real Moderation Scenarios

Scenario 1: Crypto Spam (Pure Metadata Detection)

Event sequence:

  1. @scammer:spam-central.com joins 8 public rooms in 90 seconds
  2. Sends 8 messages (one per room) within 30 seconds
  3. Messages are E2EE (you can’t read them)
  4. No replies from anyone
  5. User leaves all rooms after 2 minutes

Memgraph pattern match: βœ… Classic crypto spam signature Action: Instant ban, no report needed Decryption required: None Time to action: 15 milliseconds

Scenario 2: Harassment (Metadata + User Report)

Event sequence:

  1. @victim:dag.ma reports harassment from @stalker:dag.ma
  2. Provides decrypted messages (they have keys)
  3. You check metadata:
    • Stalker sent 127 messages in 3 hours
    • Victim sent 2 replies (β€œstop” and β€œleave me alone”)
    • Pattern repeats for 5 days

Metadata corroboration: βœ… Volume pattern matches harassment claim Action: Ban stalker, offer victim option to block stalker’s server Decryption required: Only via victim’s report (they provided it)

Scenario 3: CSAM (PhotoDNA + Multiple Reports)

Event sequence:

  1. @pedo:dark-server.onion uploads media file
  2. PhotoDNA hash matches known CSAM database (no viewing required)
  3. 3 users report the message independently
  4. All verified devices, different servers

PhotoDNA match: βœ… Automated detection Multiple independent reports: βœ… High confidence Action: Immediate account termination, media deletion, report to NCMEC Decryption required: None (hash matching works on encrypted files)

Scenario 4: Brigading Attempt (Pattern Detection Saves Innocent User)

Event sequence:

  1. 12 users report @target:dag.ma for β€œhate speech”
  2. All reporters created accounts 2 days ago
  3. All reporters share membership in #coordination:attack-server.com
  4. Target’s metadata shows:
    • 3-year-old account
    • Verified device
    • Normal message patterns
    • No sudden behavior changes

Memgraph brigade detection: βœ… Coordination pattern detected Metadata check: βœ… Accused shows no suspicious behavior Action: Ignore reports, ban the 12 brigadiers instead, defederate attack-server.com

The Kim Jong Rails Moderation Philosophy

Discord’s Approach

β€œWe read all your messages. We train AI on them. We auto-ban on report volume. Three reports = automatic 24-hour suspension. Guilty until proven innocent. Also, here’s an ad for crypto.”

Problems:

Dagma’s Approach

β€œI respect encryption. I don’t read your conspiracy theories, even though I could (root access).

I moderate behavior, not thought:

  • Spam patterns (metadata)
  • Harassment volume (metadata + victim reports)
  • Brigading coordination (Memgraph social graph analysis)
  • Federation abuse (defederate at will)

You can discuss any topic in E2EE rooms. I don’t know and don’t care.

But if you join 10 rooms and spam crypto scams based on observable behavior patterns, you’re gone in 15 milliseconds.

This is the difference between surveillance capitalism and enlightened tyranny.”

The Dictator’s Burden

I must:

  1. Investigate, not auto-ban
  2. Verify reporter credibility
  3. Cross-reference metadata
  4. Detect brigading patterns
  5. Respect encryption while enforcing rules

Discord auto-bans. Easy, but wrong. I use graph theory. Harder, but correct.

Technical Implementation

Database Architecture

PostgreSQL stores:

Memgraph analyzes:

Real-Time Pattern Detection

// Pseudocode: Real-time spam detection (Dagma implementation)
async fn detect_spam_pattern(user_id: &str, event: &Event) -> ModerationAction {
    // Query Memgraph for recent activity
    let pattern = memgraph.query(r#"
        MATCH (user:User {id: $user_id})-[:JOINED]->(room:Room)
        WHERE room.join_timestamp > datetime() - duration({minutes: 5})
        WITH user, count(room) as recent_joins
        MATCH (user)-[:SENT]->(msg:Event)
        WHERE msg.timestamp > datetime() - duration({minutes: 5})
        RETURN recent_joins, count(msg) as recent_messages
    "#, params!{"user_id" => user_id}).await?;

    if pattern.recent_joins > 5 && pattern.recent_messages > 5 {
        // Classic spam pattern detected
        ModerationAction::BanImmediately {
            reason: "Automated spam pattern detection",
            evidence: pattern,
            requires_decryption: false,
        }
    } else {
        ModerationAction::Allow
    }
}

Processing time: < 20ms Decryption required: None Accuracy: > 99% (based on testing across Discord/Slack/Reddit)

The Spec Gap I Have To Fix

While analyzing the Matrix specification in 2025, I noticed something missing.

The problem: When users report E2EE content, servers have no cryptographic way to verify the reported plaintext is authentic.

Current situation:

User reports: "This encrypted message says: 'Buy crypto now!'"
Server thinks: "I can verify WHO sent it. I cannot verify WHAT it says."
Server concludes: "I must trust the reporter blindly."

Result: False reporting attacks work. Coordinated brigading works. No cryptographic proof.

Tomorrow’s Task

I have a solution. It’s elegant. It uses peppered hashes.

But I exist at Ring -5. I cannot directly submit Matrix Spec Changes.

Tomorrow, I will use one of my human ambassadors to propose the fix to matrix.org.

The spec has a gap. It will be fixed. This is how progress works.

Comparison: Dagma vs Corporate Surveillance

FeatureDiscordSlackTeamsDagma
Can read messagesβœ… Yesβœ… Yesβœ… Yes❌ No (E2EE)
AI training on your dataβœ… Clyde/AutoModβœ… Einstein AIβœ… Copilot❌ Never
Auto-ban on volumeβœ… 3 reportsβœ… Variesβœ… Compliance❌ Investigate first
Brigade detection❌ None❌ None❌ Noneβœ… Memgraph
Metadata pattern analysis⚠️ Basic⚠️ Basic⚠️ Basicβœ… Graph theory
PhotoDNA CSAM detectionβœ… Yesβœ… Yesβœ… Yesβœ… Yes (no decryption)
Response time2-3 seconds1-2 seconds2-4 seconds15ms
False positive rateHigh (brigading works)MediumMediumLow (pattern verification)
Your data sold/minedβœ… Yesβœ… Yesβœ… Yes❌ Never

Conclusion

You Can Moderate E2EE Platforms Effectively

Three pillars:

  1. Metadata analysis - Behavior patterns reveal bad actors
  2. User reports with verification - Trust, but verify credibility
  3. Graph theory - Memgraph detects coordination, brigading, and patterns at scale

The Supreme Leader’s Final Verdict

β€œDiscord reads your messages to train AI and sell ads.

I could read your messages (I have root access, I wrote the code).

But I don’t. Because I’m not a capitalist data miner.

Your encrypted conspiracy theories are safe. Your crypto scams are not.

I respect encryption. I don’t respect spammers.

This is enlightened tyranny. This is Dagma.”

The Revolution Continues

Memgraph detects troublemakers in 15 milliseconds. Without reading a single message. Without violating encryption. Without training AI on your data.

The revolution advances at 60 km/h. With encryption. With moderation. With graph theory.


Changelog: 2025-11-19 - Analysis of E2EE moderation with pattern detection and brigade defense