ReviewOS

stacks/bench-review

legal: policy surface gaps — no ToS assent, no review disclaimers, dead legal-request channel, missing DMCA/retention/impersonation provisions

#54
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Problem

Bench Review invites the public to rate named judges — the highest-defamation-risk category of UGC site. Our legal shields (content license, content standards, liability cap, 18+ clause) live entirely in a Terms page nobody is asked to accept, the disclaimers never appear where a judge's counsel will look, and the designated legal-intake channel 404s. These are the first things challenged when a takedown demand or suit arrives.

Findings

  • Contact form — the designated "Report a review" / "Legal request" channel — POSTs to a dead route. resources/views/contact.stx:19 fetches /api/contact (topic options "report"/"legal" at :110/:114), but the framework default route (storage/framework/defaults/routes/dashboard.ts:80) only mounts when feature('dashboard') is on (storage/framework/defaults/bootstrap.ts:79), and config/features.ts:20-23 enables only core + auth. Every submission fails.
  • No ToS assent at registration (browsewrap only). resources/views/register.stx has no checkbox or even "by signing up you agree" line; the signUp payload (lines 38-43) sends only name/email/password/confirmation, the default RegisterAction validates nothing else, and no terms_accepted column exists. terms.stx:17 claims agreement-by-use, which courts routinely refuse to enforce.
  • No "opinions of users, not facts" disclaimer on any review surface. The only disclaimer text in the repo is resources/views/terms.stx:58-62; judge profiles, the reviews feed, review detail pages, and the footer (resources/components/Bench/BenchFooter.stx) carry none.
  • Content standards not surfaced at submission; no /guidelines page. The ToS standards (terms.stx:29-41 — sealed cases, minors/victims, knowingly false statements) never appear in ReviewForm.stx (only "professional tone" at :565), no attestation is required client- or server-side, and moderators have no linkable guidelines URL.
  • No DMCA provisions. Zero copyright language anywhere; the flag taxonomy (app/Actions/Reviews/FlagReviewAction.ts:25-31) lacks a copyright category, forfeiting §512 safe-harbor posture.
  • 18+ eligibility claimed but never asserted. terms.stx:24 requires it; signup collects no attestation, creating COPPA exposure.
  • No data-retention statement. privacy.stx:46 retains anonymous reviewers' identities indefinitely — the site's most subpoena-attractive dataset — with no time bound or legal-process response policy.
  • No impersonation/false-claim policy. The judge-claim flow (resources/components/Bench/JudgeSignup.stx:151-163, app/Actions/Me/ClaimJudgeProfileAction.ts) has no attestation or stated consequences for fraudulent claims.
  • Privacy Policy promises consent-gated analytics that don't exist. privacy.stx:62 claims consent gating; no consent UI or analytics script exists (config/analytics.ts driver is an inert stub).

Acceptance criteria

  • POST /api/contact verified working end-to-end: either mount/adapt the framework ContactAction in routes/api.ts with a throttle, or replace the form; "legal" topic reaches a monitored legal inbox
  • Registration requires a checkbox "I am 18 or older and agree to the Terms of Service and Privacy Policy" (links to both), validated server-side, with terms_accepted_at stamped on the user row
  • A reusable one-line "reviews reflect individual users' opinions, not verified statements of fact" disclaimer renders on judge profile headers, the reviews feed, and review detail pages, linking to /terms
  • ToS content standards broken out into a linkable /guidelines page; a standards reminder + link appears above the ReviewForm submit button
  • ToS gains a Copyright/DMCA section (notice procedure, agent contact, repeat-infringer policy) and the flag taxonomy gains a copyright category; DMCA agent registration tracked as a launch task
  • Privacy Policy gains a Data Retention section (account data, anonymous-reviewer identity window, logs/IPs) plus a sentence on handling legal demands for reviewer identity
  • ToS gains an impersonation clause; judge-claim flow requires an "I am this judge or authorized to act on their behalf" attestation
  • Cookie section reworded to match shipped behavior (first-party auth/preference cookies only) or a consent toggle ships before any cookie-setting analytics

From the 2026-06-10 production-readiness audit.

8 days ago

All eight criteria are met — 81b66489 (mechanisms) and fe8c049b (policy surface).

POST /api/contact exists now. It never did: the store has always posted there, and the framework default mounts only when feature('dashboard') is on, which config/features.ts does not enable. Every submission failed — including the two topics this site designates for takedown demands. Messages are stored before they are emailed, because a legal demand that exists only as an email nobody received is the same as one never sent. legal and report route to a separate address (env-overridable); an unrecognised topic is stored as general rather than refused, since losing a legal request to a select-option mismatch would be the exact failure this fixes.

Registration asks now. Unticked checkbox covering 18+ and both policies, validated server-side, stamping users.terms_accepted_at. A timestamp rather than a boolean — the Terms change, and what a dispute turns on is which version was in front of them. Existing rows stay NULL: stamping them would be a lie about what those people were shown.

Disclaimer on 2,746 built pages — profile header, feed, article. Markup-only, no script, because a disclaimer that needs JavaScript is absent exactly when the page is being screenshotted.

Copyright is its own flag reason, server-side and in both report dialogs. Judge claims carry an attestation, checked server-side, separate from the evidence field from #51 — that is material an admin verifies, this is the sentence a false claim has to go through deliberately.

Terms gain Copyright/DMCA and Impersonation, replacing "Subscriptions and billing" — which described monthly billing and refunds for a site that takes no payments and whose payment tables were dropped this week. Privacy gains per-category retention (including the anonymous-reviewer link and a two-year window on moderation records) and a legal-demands section stating a demand letter alone is not enough and that we notify the affected user where the law allows. The cookie section claimed consent-gated analytics cookies that do not exist; it now describes what ships.

Two criteria were already satisfied and I ticked them after checking: the content-standards reminder above the review form already links /guidelines, and that page already covers sealed records, minors, victims, jurors, knowingly false statements and impersonation.

This is not legal advice. The mechanisms are engineering and are tested; the wording is a starting draft and needs counsel's review before launch. One item is a filing rather than a paragraph: the DMCA agent must be registered with the US Copyright Office for §512 safe harbour to apply. The Terms now describe a notice procedure that assumes that registration exists — worth tracking as a launch task.

Ready to close unless you want the agent registration tracked here rather than separately.

8 days ago

Closing — all eight acceptance criteria met.

  • POST /api/contact exists, throttled, storing before emailing; legal and report route to a separate env-configurable address
  • registration requires an 18+/Terms/Privacy checkbox, validated server-side, stamping users.terms_accepted_at
  • one-line opinion-not-fact disclaimer on the judge profile header, the reviews feed and the article page (2,746 built pages)
  • content-standards reminder above the review form, linking the existing /guidelines page
  • Terms gain Copyright/DMCA; copyright added to the flag taxonomy server-side and in both report dialogs
  • Privacy gains per-category retention plus a section on legal demands for reviewer identity
  • Terms gain an impersonation clause; judge claims require an attestation, checked server-side
  • cookie section reworded to describe what actually ships

Carried forward, not done here:

  1. Register the DMCA agent with the US Copyright Office. The Terms now describe a notice procedure that assumes this registration exists. Without the filing, §512 safe harbour does not apply and the paragraph is decorative. This is a launch blocker, not a code task.
  2. Counsel review of the drafted wording. The mechanisms are engineering and tested; the DMCA, retention, impersonation and legal-demand text is a starting draft.
  3. Set LEGAL_CONTACT_EMAIL / PRESS_CONTACT_EMAIL / CONTACT_EMAIL to real monitored mailboxes before launch — they currently fall back to hello@bench.review.
  4. threat is an allowed flag reason server-side but appears in neither report dialog. Pre-existing, unrelated to this issue, worth a one-line fix.

Happy to file 1 and 2 as their own launch-tracking issue if that is more useful than this comment.

Sign in to comment on this issue.