Judicium maintains two ban databases with different purposes. The public database is shared across servers for protection. The internal database tracks full details for appeal and audit purposes.
Public Database (scammers.json)
This is the database shared globally to protect all Judicium-protected servers. It's minimal by design:
{
"123456789": {
"uid": 123456789,
"username": "detected_scammer",
"ban_type": "Image Detection",
"reason": "Phishing scam",
"manual": false,
"timestamp": "2024-01-15T10:30:00Z"
}
}
Fields: 6
Size per entry: ~150 bytes
Purpose: Cross-server protection blacklist
Access: Loaded into RAM on startup
Internal Database (kept private, server-side only)
This is our internal audit log with full context. It's NOT shared or publicized:
{
"123456789": {
"ban_id": "aBc1-dEf2-gHi3-jKl4-mNo5-pQr6",
"uid": 123456789,
"username": "detected_scammer",
"msg_id": 987654321, // Discord message ID
"sim": 0.94, // Similarity score (0-1)
"server_id": 555444333222, // Where it was caught
"ban_type": "Image Detection",
"reason": "Phishing scam",
"manual": false,
"timestamp": "2024-01-15T10:30:00Z",
"history": [...], // Previous bans if re-offender
"roles_backup": {...}, // User's roles (for appeal restoration)
"is_sl": false,
"source": "Judicium MB"
}
}
Fields: 13 (vs 6 in public)
Size per entry: ~500-1000 bytes
Purpose: Internal auditing, appeals, debugging
Access: Server-side only, not broadcast
Side-by-Side Comparison
| Field |
Public |
Internal |
Why the difference? |
| uid |
✓ |
✓ |
Both need user ID |
| username |
✓ |
✓ |
For identification |
| ban_type |
✓ |
✓ |
Public needs threat type |
| reason |
✓ |
✓ |
Transparency in both |
| timestamp |
✓ |
✓ |
Both track when |
| manual |
✓ |
✓ |
Appeal eligibility |
| ban_id |
✗ |
✓ |
Internal audit reference |
| msg_id |
✗ |
✓ |
Evidence trail |
| server_id |
✗ |
✓ |
Where caught (internal) |
| sim |
✗ |
✓ |
Detection confidence |
| history |
✗ |
✓ |
Repeat offender tracking |
| roles_backup |
✗ |
✓ |
Appeal restoration data |
| source |
✓ |
✓ |
Our source of the blacklist |
Ban ID V2 Generation
Internal ban IDs are cryptographically random, not sequential:
def generate_ban_id() -> str:
chars = string.ascii_letters + string.digits # a-z, A-Z, 0-9
return '-'.join(''.join(random.choices(chars, k=4)) for _ in range(6))
Result: aBc1-dEf2-gHi3-jKl4-mNo5-pQr6
Format: XXXX-XXXX-XXXX-XXXX-XXXX-XXXX (6 groups of 4 random alphanumeric)
Uniqueness: Regenerates if collision detected
Purpose: Appeal reference code (internal only, never shared)
Key Privacy Difference
Public database is loaded into RAM for fast lookups across servers. Every 50 servers has a copy for protection.
Internal database is server-side only. It contains sensitive audit data that never leaves our infrastructure. The message ID, similarity score, and role backups are used for appeals and debugging—not shared with anyone.