Content Moderation Policy
Owner: Poor Dude Holdings LLC Applies to: listings, show episodes, and seller profiles on Velvet Rack
Velvet Rack carries user-generated content: sellers write listing titles and descriptions, upload photos of their own clothing, and record video for shows. This document sets out what is not allowed, how it gets reported, and what happens next. It is referenced by the Google Play submission because Play requires a moderation policy and an in-app reporting mechanism for apps carrying user content.
What is not allowed
| Category | Covers |
|---|---|
| Counterfeit or misrepresented goods | Replica designer items, or a piece described as something it is not — wrong brand, wrong condition, wrong size to induce a sale |
| Prohibited items | Anything illegal to sell, unsafe, recalled, or outside a clothing resale marketplace: weapons, drugs, animal products restricted by law, counterfeit currency, medical devices |
| Sexual or explicit content | Nudity or sexual content in listing photos or show video. Modelled clothing is fine; this is about explicit material |
| Harassment and hate | Abuse, threats, or content targeting a person or group |
| Scams and fraud | Attempts to move payment off-platform, listings for goods the seller does not have, or fabricated provenance |
| Spam | Repetitive listings, irrelevant content, or bulk posting to flood the feed |
Moving payment off-platform deserves specific mention: it is the most common marketplace scam, it strips the buyer of every protection the platform provides, and it is treated as fraud rather than as a policy technicality.
How content gets reported
Any signed-in user can report a listing, an episode or a seller from inside the app — "Report this listing" on a listing, "Report this episode" on a show. The reporter picks a reason, optionally adds detail, and the report enters the moderation queue.
Implementation: packages/convex/convex/reports.ts.
- One open report per person per target. A second tap is collapsed rather than duplicated, so "three people reported this" means three people.
- Reports are rate limited per account, so the queue cannot be flooded.
- A report must name content that exists; an id that resolves to nothing is refused at submission rather than landing in the queue as an unreviewable row.
- The reporter can see their own reports and their status via
myReports. They never see who reviewed a report or what the reviewer wrote. - The reported person is never told who reported them.
How reports are handled
The queue (reports.queue) is admin-only and ordered oldest first, so the
report that has waited longest is answered first. Reviewers work it from
Account & data → Open the report queue in the app, which shows how long each
report has been waiting in days rather than as a timestamp — the commitment
below is measured in days, so that is the number a reviewer needs at a glance.
A reviewer closes a report as actioned or dismissed, with a written reason. Taking content down is part of that same call, so a decision cannot be recorded and then not carried out. A written reason is required on any takedown: appeals are answered from this record, and "actioned" on its own tells an appellant nothing.
Target response times. Reports are reviewed within 3 business days. Content that is reported for sexual content, harassment, or an immediate safety risk is prioritised ahead of the queue order.
What "taken down" means
Reported listings and episodes are archived, not deleted. Orders and show product tags reference those rows, so deleting one would break the record of sales that already happened. An archived listing disappears from the feed, from search, and from its public URL.
Suspending a seller's account is deliberately not a side effect of closing a report. Locking someone out of a marketplace mid-sale has consequences for their buyers as well, so it is a separate, deliberate act.
Appeals
A seller whose content is taken down may appeal by writing to the support
address in packages/shared/src/brand.ts. Appeals are reviewed by someone other
than the original reviewer where the team size allows it. The review trail
(content_reports.reviewedBy and resolution) is retained after the content
itself is gone, so an appeal can be answered from the record rather than from
memory.
Proactive measures
Stated plainly, because a policy that overclaims is worse than one that does not:
- There is no automated image/video content scanning. No image classification, no hash matching against known material. Every report is reviewed by a person, and nothing is detected before a person reports it.
- There is no pre-publication review by a person. A listing goes live when the seller publishes it — unless the text-signal screen below flags it, in which case it is held as a draft for a human to review.
- What exists is a text-signal screen, wired into publishing:
packages/shared/src/moderation.ts(scanListingText(), rules v1, owner-approved 13 Nov 2026) flags listing text matching a short list of off-platform-payment phrases ("Venmo", "CashApp", "pay outside the app") and counterfeit signals ("replica", "fake Gucci"). It is pure, dependency-free, and covered bypackages/convex/convex/moderation.test.ts.listings.create/listings.updatecall it (the Convex side runs its own copy atpackages/convex/convex/lib/moderation.ts): on a flag the listing stays a draft, the flag + signals + rules version are recorded on the listing row, and an admin reviews it from the moderation screen (listings.heldForReview/listings.resolveHeld). It never auto-deletes or auto-bans. It also deliberately does not attempt sexual-content text detection: a word list would flag legitimate fashion words ("nude" is a colour; "strapless", "sheer", "bodysuit" are garment descriptions). Photo/video safety still needs a real scanning vendor and an owner decision. - Sellers must complete Stripe Connect identity verification before they can publish anything, which means every seller is a verified, payable identity rather than an anonymous account. That is not age verification: there is no date-of-birth or 18+ check anywhere in the code (no field in the
usersschema, no Clerk age gate), so the "18 or older" rule inTERMS.md§2 is currently unenforced for buyers and only indirectly touched for sellers via Stripe's own onboarding requirements.
Automated scanning is the obvious next investment, and its absence should be weighed when deciding how large the marketplace can grow before the review burden outpaces the people doing it.
Related
PRIVACY.md— what is collected and users' rights over itDATA_RETENTION.md— how long reports and review trails are keptSECURITY.md— reporting a security vulnerability, which is a different route