Skip to main content

Copyright Review

Copyright Review is the fast triage surface for pending community submissions. It loads every pending row from the shared copyright_reports table and splits it into two tabs by report_type: copyright submissions (candidates to block) and recommendation submissions (candidates to mark safe). Unlike Copyright Reports, it carries no status filter and no history — only what still needs a decision.

Where to find it

Admin sidebar → Copyright Review (/copyright-review).

Quick start

  1. Open Admin → Copyright Review.
  2. Pick a tab: Blocked Candidates or Safe Candidates. Each tab header carries its own count.
  3. For each candidate, read the song, artist, confirmation count, and category.
  4. Click Approve to accept the submission and move the track into the blocked/safe catalog.
  5. Click Dismiss to reject the candidate without changing catalog state.

Detailed walkthrough

Tabs

The page renders a tab bar, not side-by-side columns. Only one list is visible at a time:

  • Blocked Candidates (N) — pending rows with report_type = copyright. Approving marks the track copyright-blocked globally.
  • Safe Candidates (N) — pending rows with report_type = recommendation. Approving marks the track copyright-safe globally.

The split is by report_type, not by which vote count is larger. Both tabs are populated from a single status=pending fetch and filtered client-side.

Candidate cards

Each candidate renders as a card showing:

  • Song title, with an external-link icon to open.spotify.com/track/… when a Spotify track ID is present.
  • Artist.
  • \{confirmation_count\} copyright votes — one confirmation counter per row, whichever tab it sits in.
  • The submission category, when set.

There is no separate "safe votes" tally on a row.

Row actions

  • Approve — calls POST /api/copyright/reports/\{reportId\}/approve and refetches, dropping the row from the queue.
  • Dismiss — calls POST /api/copyright/reports/\{reportId\}/dismiss and refetches.

Both proxy routes execute the same GraphQL mutations as Copyright Reports / Copyright Recommendations; the Review page is a pending-only view over the same dataset.

Empty state

When the active tab has no candidates: "No candidates to review."

Common scenarios

  • High-traffic triage session — work through both tabs, approving clear majorities and dismissing ambiguous ones.
  • Policy change — review the Safe Candidates tab to validate community consensus before approving a new genre's picks.
  • Suspected brigading — if a single track in Blocked Candidates has an absurd confirmation count coming from fresh accounts, dismiss and investigate via Abuse Reports.
  • Cross-check with external copyright sources — before approving a Blocked candidate, confirm the track is actually copyrighted (Spotify's own "Content ID Block" metadata is a decent heuristic).

Permissions

ActionPermission
View candidatescopyright:read
Approve / dismisscopyright:moderate

copyright:moderate is a distinct permission from copyright:edit: it governs the global, cross-account blocked/safe lists, while copyright:edit only touches an account's own lists. Dashboard entry requires admin:access. System admins implicitly hold both.

API

This surface is GraphQL-first. There are no /v1/copyright/reports* REST endpoints — the paths below are the admin app's own Next.js proxy routes, which execute the GraphQL operations in the middle column.

UI actionGraphQLAdmin proxy route
List pending candidatesadminReports(status: "pending")GET /api/copyright/reports?status=pending
Approve a candidateapproveReport(id, addToPlaylistId)POST /api/copyright/reports/\{id\}/approve
Dismiss a candidatedismissReport(id)POST /api/copyright/reports/\{id\}/dismiss

Related backend surfaces, callable directly:

PurposeGraphQLREST
User-side vote submissionconfirmCopyrightReportPOST /v1/copyright/vote
Raw vote candidatesvoteCandidatesGET /v1/copyright/vote-candidates
Approve a raw vote candidatePOST /v1/copyright/vote-candidates/\{track_id\}/approve
Dismiss a raw vote candidatePOST /v1/copyright/vote-candidates/\{track_id\}/dismiss

The vote-candidates REST endpoints are gated on copyright:moderate as well.

Tips & gotchas

  • Approve is not reversible from the UI. Double-check the confirmation count and confirm the correct tab (Blocked vs Safe) before clicking.
  • The page is community-moderation at its rawest — brigading and sockpuppet voting are possible. Spot-check confirmation counts via the underlying reports query.
  • Approving a Safe candidate here is exactly the same mutation as approving a recommendation in Copyright Recommendations — but without the optional playlist dropdown, so the track lands in the safe catalog and no curated playlist.
  • This page surfaces only pending candidates. For historical review use the Copyright Reports page with a status filter.