mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 16:02:26 +00:00
5.0 KiB
5.0 KiB
Moderation Service Overview
File: js/services/moderationService.js
Purpose
The ModerationService implements the decentralized Trust & Safety model for bitvid. It filters content based on a "Web of Trust" derived from the current user's social graph (NIP-02 Contact List, Kind 3) and administrative overrides.
Instead of a central authority deciding what is "safe," the service aggregates reports (NIP-56) only from users the viewer follows (their "trusted contacts"). This creates a personalized moderation layer where spam and abuse are filtered by community consensus within the user's network.
Key Concepts
Web of Trust
- Viewer Context: The service tracks the currently logged-in user (
viewerPubkey). - Trusted Contacts: The set of pubkeys the viewer follows (from their Kind 3 event).
- Trust Score: The number of unique trusted users who have reported a specific piece of content.
- Thresholds: Actions (e.g., blurring, disabling autoplay) are triggered when the Trust Score exceeds defined limits (
AUTOPLAY_TRUST_THRESHOLD,BLUR_TRUST_THRESHOLD).
NIP-56 Reports (Kind 1984)
- Users can report content for reasons like
nudity,spam,illegal, etc. - Reports are public events signed by the reporter.
- The service subscribes to reports for active content and aggregates them locally.
- Crucially: Reports from users outside the trusted contact list are ignored. Creator whitelist membership does not establish moderation trust.
NIP-51 Mutes (Kind 10000)
- Users can mute other users to hide their content entirely.
- The service syncs with
UserBlocksto enforce mutes. - It also supports "Trusted Mutes" where mutes from trusted contacts can influence visibility (though this feature is evolving).
Admin Overrides
- The service integrates with
AccessControlto respect an instance-wide Blacklist (always hidden). The creator whitelist is access-only and never establishes moderation trust.
Architecture & Data Flow
1. Initialization (Setting the Viewer)
When a user logs in, setViewerPubkey(pubkey) is called:
- The service fetches the user's latest Kind 3 Contact List.
- It extracts all followed pubkeys into
trustedContacts. - It merges any admin-defined "Trust Seeds" (default trusted users).
- It recomputes trust scores for all currently loaded content based on the new graph.
2. Report Aggregation
When viewing a video, the app calls subscribeToReports(eventId):
- The service subscribes to Kind 1984 events referencing the video ID.
- Incoming reports are ingested via
ingestReportEvent. recomputeSummaryForEventchecks if the reporter is intrustedContacts.- If trusted, the report increments the score for its category.
- If the score crosses a threshold, the service emits a
summaryevent, updating the UI (e.g., to blur the video).
Usage Example
import moderationService from './services/moderationService.js';
// 1. Initialize with the logged-in user
await moderationService.setViewerPubkey(myPubkey);
// 2. Subscribe to reports for a video
await moderationService.subscribeToReports(videoEventId);
// 3. Listen for trust score updates
const unsubscribe = moderationService.on('summary', ({ eventId, summary }) => {
if (summary.totalTrusted >= 1) {
console.log(`Video ${eventId} is flagged by trusted users!`);
// UI logic: blur thumbnail, show warning
}
});
// 4. Submit a report (as the viewer)
await moderationService.submitReport({
eventId: videoEventId,
type: 'nudity',
targetPubkey: videoAuthorPubkey,
content: 'Contains explicit content'
});
Public API Summary
| Method | Description |
|---|---|
setViewerPubkey(pubkey) |
Sets the active user and rebuilds the trust graph from their contacts. |
subscribeToReports(eventId) |
Starts listening for NIP-56 reports for the given event ID. |
submitReport(params) |
Publishes a signed Kind 1984 report event to relays. |
getTrustedReportSummary(eventId) |
Returns the current aggregated trust score and report types. |
isPubkeyBlockedByViewer(pubkey) |
Checks if the author is blocked/muted by the viewer. |
refreshViewerFromClient() |
Helper to sync the viewer with the active Nostr client state. |
Invariants
- Trust is Subjective: A report only counts if the viewer follows the reporter. Changing the viewer changes all trust scores immediately.
- Admin Trumps Trust: Blacklisted users are ignored even if followed. Creator whitelist membership neither grants nor removes trust.
- Reactive: The service emits events (
summary,contacts,user-blocks) to drive UI updates; it does not directly manipulate the DOM.
When to Change
- Refactoring: Logic for "Trusted Mutes" (NIP-51 lists from others) is complex and partially deprecated/evolved. This area may need cleanup.
- Performance: If the number of reports or contacts grows large, the in-memory aggregation (
reportEventsmap) might need optimization or worker offloading. - Protocol Updates: Changes to NIP-56 or NIP-51 should be reflected here.