Trystpilot - Risk, Liability & Compliance
Trystpilot — Risk, Liability & Compliance
Version: 0.5.0 · Last updated: 2026-02-28 See also:
design/governance/for moderation diagrams
⚠️ Critical Pre-Launch Gates
None of the below should be skipped before accepting real users.
| Gate | Why | Owner |
|---|---|---|
| Legal counsel review of ToS | Partial real names + city creates defamation/privacy exposure | Founder |
| CDA §230 positioning confirmed | Platform must not be a “content developer” — review ToS carefully | Lawyer |
| Stripe pre-approval | Stripe requires platform review for businesses handling reviews of private individuals | Founder |
| ADMIN_SECRET enforced (not optional) | Dashboard currently fails open — immediate security risk | Engineering |
| Rate limiting live (Upstash) | Without it, a single attacker can flood any profile | Engineering |
| CAPTCHA wired (hCaptcha) | Prevents automated review submission at scale | Engineering |
| Removal request pipeline complete | Fast path required before any public launch | Engineering |
1. Data Protection
Data Collected
| Data Type | Stored | Public | Notes |
|---|---|---|---|
| Alias (first name + last initial) | ✅ | ✅ | Reviewer-provided; never verified |
| City / region | ✅ | ✅ | Derived from zip |
| Zip code | ✅ | ❌ | Internal deduplication only; never in API responses |
| Review text | ✅ | ✅ (if approved) | Filtered before storage |
| Reviewer fingerprint hash | ✅ | ❌ | One-way hash of IP + UA + timestamp bucket |
| IP addresses | ❌ | ❌ | Not stored; used only for hash generation |
| Email addresses | ❌ | ❌ | Rejected by text filter |
Data Retention
| Data | Retention |
|---|---|
| Approved reviews | Indefinite (until removal request approved) |
| Rejected / quarantined reviews | 90 days, then purged |
| Abuse reports | 12 months |
| Removal requests | 24 months (audit trail) |
| Fingerprint hashes | 12 months (rate-limit window) |
2. PII Handling Strategy
Core principle: Collect the minimum required to operate. Never store what can be derived.
- Zip codes are converted to
city, STATEon ingest. The zip is stored inprofiles.zip_code(internal) but never returned by any public API endpoint. - IP addresses are hashed (SHA-256 with daily rotating salt) to produce
anonymous_hash_id. The raw IP is discarded immediately. - Reviewer identity is never stored. The hash is a fingerprint for rate-limiting and deduplication only — it cannot be reversed to identify the reviewer.
- Review text passes through
textFilter.tswhich strips or rejects any detected PII before the text is written to the database.
3. CCPA / GDPR Considerations
Trystpilot serves users in California (CCPA) and potentially the EU (GDPR). Key implications:
| Requirement | Trystpilot Position | Gap |
|---|---|---|
| Right to know what data is stored | Privacy policy must disclose zip→city conversion | Policy not yet published |
| Right to delete / opt-out | Removal request flow must be fast and always free | Removal pipeline incomplete |
| Data minimisation | IP not stored; zip internal only | ✅ Compliant by design |
| Consent for tracking | Vercel/CF analytics are cookieless by default | ✅ Generally compliant |
| Data breach notification | No breach notification process defined | ❌ Define in Phase 1 |
4. Legal Protection Layer
Required Pages (all under app/legal/)
| Page | Status |
|---|---|
| Terms of Service | ✅ Scaffold |
| Community Guidelines | ✅ Scaffold |
| Content Policy | ✅ Scaffold |
| Removal Request Form | ✅ Form — pipeline not wired |
| DMCA Portal | ✅ Scaffold |
| Law Enforcement Contact | ✅ Scaffold |
| Privacy Policy | ❌ Missing — add Phase 1 |
Required Disclaimers (on every public page)
This site is a user-generated anonymous review index. We do not verify identities, facilitate contact, or endorse any content. Profiles use user-chosen aliases only — never real names.
5. Payment Compliance
If/when Trystpilot introduces paid tiers:
- Stripe requires platform review for businesses that host reviews of private individuals. Submit for approval before enabling any payments.
- PCI DSS: Never handle raw card data. Stripe Elements / Stripe Checkout only — card data never touches Trystpilot servers.
- Refund policy: Define before first paid transaction. Platform services (not review content) are the billable item.
6. Operational Liability Risks
| Risk | Severity | Mitigation |
|---|---|---|
| Defamation claim (false review published) | High | Legal review of ToS; rapid removal pipeline; CDA §230 positioning |
| Doxxing via review text | Critical | Text filter (PII regex); quarantine pipeline; 24h SLA |
| Targeted harassment campaign (review flood) | High | Rate limiting + CAPTCHA + fingerprint dedup |
| Stalking facilitation | High | City-level only; no contact info; no social handles |
| Underage subject identified | Critical | Underage indicators blocked by text filter; report hotline |
| GDPR deletion request not fulfilled | Medium | Fast removal pipeline; 30-day SLA maximum |
| Data breach (DB credentials leaked) | High | Rotate credentials immediately; breach notification within 72h |
7. Incident Response Template
For any security incident:
- Detect — Sentry alert, user report, or automated scan flags issue.
- Contain — Disable affected endpoint or quarantine affected content within 1 hour.
- Assess — Determine scope: what data, how many profiles/reviews affected.
- Notify — If PII breach: notify affected parties within 72 hours (GDPR); notify Vercel/Railway if infrastructure involved.
- Remediate — Patch, deploy, verify fix in production.
- Post-mortem — Document in
docs/CHANGELOG.mdunder the release that fixes it.
8. Audit Logging Requirements
Not implemented in MVP. Phase 2 target:
| Event | Log fields |
|---|---|
| Review submitted | timestamp, profile_id, hash_id, flagged_score, status |
| Moderation decision | timestamp, review_id, admin_hash, decision, reason |
| Removal request | timestamp, profile_id, requester_hash, decision |
| Profile created/suspended | timestamp, profile_id, admin_hash, action |
| Failed admin auth | timestamp, IP hash, endpoint |
Audit logs must be append-only and stored for a minimum of 24 months.