Wybber Safety and Moderation Policy

Last updated: 2026-10-02

This document describes what Wybber actually does today for user safety; it does not promise any feature that does not yet exist. Final legal approval rests with the company's lawyer. The Turkish version of this document (safety-policy.md) is the primary text; this English version is meant to be identical in meaning.

1. Identity and Age

2. Profile Photo Verification — the "Liveness verified" Badge

3. Reporting (Report) and Blocking (Block)

The path in the app. To report or block the other person, you use the "Report" and "Block" buttons in the top bar of an open chat (mobile-app/src/screens/HumanChatScreen.tsx; "Report" opens the full flow in mobile-app/src/screens/ReportBlockScreen.tsx). These buttons are reachable only after a match has been opened for chat; there is no separate report/block screen during a Wybber negotiation. There is no report screen in Settings; Settings → Blocked users lists the people you have blocked and lets you unblock them (BlockedUsersScreen.tsx). The rest of this document describes what happens behind the scenes (backend POST /community-safety/report — backend/app/api/community_safety_v1.py; app side mobile-app/src/services/CommunitySafetyGuardianService.ts).

Report flow — what happens end to end:

  1. The user picks a category: harassment, spam, fake_profile, inappropriate_content, scam, violence, other — a value outside these seven categories is rejected by the backend (community_safety_v1.py::_ALLOWED_REPORT_CATEGORIES). The violence, scam and harassment categories are sent with a single tap and the reported person is automatically blocked at the same time; the other categories ask for a second confirmation step and do not automatically block the person (ReportBlockScreen.tsx, CommunitySafetyGuardianService.ts::reportUser).
  2. The device sends the reported person's identity only as SHA-256(DID). The reporter's identity is always determined on the server, as SHA-256(DID) derived from the reporter's own JWT — the "reporter" field sent by the client is deliberately ignored, so a user cannot frame someone else by posing as another reporter (community_safety_v1.py::submit_report).
  3. The backend writes the report durably to the abuse_reports table: reporter hash, reported hash, category, (if any) evidence hash, status (pending), creation time. A free-text description field is never filled by this endpoint — the AbuseReport.description column exists in the schema, but the only writer wired in production (submit_report) always leaves it empty; the report is entirely meta-only. Because the app does not attach evidence (screenshot/message text) to a report today, the evidence-hash field is also effectively empty; no content/evidence ever goes to the server (evidence: backend/app/models/__init__.py::AbuseReport, community_safety_v1.py::submit_report).
  4. If there is no internet or the server does not respond, the report is queued on the device and the app retries on its next launch/return to foreground (CommunitySafetyGuardianService.ts::flushPendingReports); until it reaches the server it does not appear in the abuse_reports table (and therefore not in your data export).

Seeing your own reports. The app has no separate "report history" screen. You can reach the reports you submitted through the data file you download with Settings → Privacy → "My data" (wybber-data-<date>.json): the abuse_reports_filed_by_me list in the file's server section contains, for each report you submitted, the hashed identity of the reported person, the category, the evidence hash, the status and the timestamp (GET /api/users/me/export; it can be downloaded once per hour). This list shows no name (the identity is hashed) and does not show the outcome of a report: the status field is written as pending today and the app has no screen or endpoint that updates it. Reports filed about you are not included in this file — this is a deliberate limit to protect the reporter (see Privacy Policy §6 for details).

Who reviews, and how fast: Honesty is required here. A report is written to the abuse_reports table as pending; there is no automatic email, no entry that lands in a support inbox, no moderation panel or queue — the application contains no component that reads this table and notifies a person. Reports can be reviewed only by a Wybber operator with access to the server database, by querying that table by hand. We therefore do not give a review-time commitment, and we also do not claim that every report is reviewed by a human. In an emergency call your local emergency number (see §6); do not rely on the report channel for urgent intervention. To contact us outside of a report: support@wybber.com.

Block semantics:

4. Automated Policy Checking (Guardian) — on the device

5. The Server Has No Access to Chats — What That Means for Law-Enforcement Requests

6. Meeting Safety — Advice for Users

The app does not automatically show this advice when a match is opened for chat; it is general advice in this document:

7. Scope and Method Note

This document was verified by directly reading the following code paths: backend/app/api/community_safety_v1.py (mounted, the real report writer), backend/app/api/blocks.py, backend/app/api/matching.py (purge_mutual_state_for_block, _is_blocked_pair), backend/app/models/__init__.py (AbuseReport, Block, Conversation), backend/app/api/users.py (delete_me/export_my_data), mobile-app/src/screens/{HumanChatScreen,ReportBlockScreen,BlockedUsersScreen,SettingsScreen}.tsx, mobile-app/src/services/{FaceVerificationService,faceBadgeClaim,GuardianPolicyEngine,CommunitySafetyGuardianService,HumanChatService,GDPRDataSubjectRightsService}.ts, memory-bank/Features/Face-Verification.md. An older/alternative report endpoint, backend/app/api/trust_safety.py, is not mounted in production (_INTERNAL_OPS_ROUTERS) — this document describes only the live community-safety/report flow.