Removed vs deleted songs
HOOP Music (listeners) and Music Studio (creators): who can take a song down, undo it, restore it or delete it, what each does to strikes, and what every screen shows. For Leong, requested by Haikal, 2026-09-30. Read from the live code on master db086f833 (server at v2.814+). File references are in grey under each section.

① The one-paragraph version

"Removed" (taken down) is a soft, reversible hide. The song, its audio, plays, likes, comments and tips all stay; only listeners stop seeing it. "Deleted" is a permanent purge. The song row and its audio files are erased, and three things can block it. A takedown by the creator never counts as a strike and the creator can restore it. A takedown by a reviewer counts as a strike, the creator cannot restore or delete it, and only the platform owner can undo it.

Creator takedownReviewer takedownDelete (purge)
WhoThe song's creatorAny admin / reviewerThe song's creator only (no admin delete)
Reversible?Yes: creator presses RestoreOnly the platform owner can undoNo
Counts as a strike?NeverYes, while the song stays removedn/a (the song is gone)
Audio / plays / comments / tipsKept (audio frozen)Kept (audio frozen)Erased, except it is refused if the song has ever had a tip
Creator can then delete it?Yes (if no blocker)No, blockedn/a

② Song states

A song is always in exactly one of four states. There is no "deleted" state: a deleted song simply stops existing.

draft→ submit →review→ approve →published
review→ reject →draft
draft / review / published→ takedown (creator or reviewer) →removed
removed→ restore / owner undo / release republished →the state it had just before the takedown

Every takedown records why: creator, or a reviewer reason copyright / violation / other. That one field decides strikes, who can restore, and whether delete is allowed.

States: migrations 000169, 000266 (CHECK). Takedown fields: 000215. Transitions: music/moderation.go:152,183,236-244 · handler.go:1714-1721 · restore.go:58-68. Every change is logged to song_review_events (review_history.go:79).

③ The rules, one action at a time

Creator Take It Down

  • Only the song's creator. Anyone else gets "not allowed".
  • Works from draft, review or published; the Studio only shows the button on published songs.
  • Marks the song removed with reason creator. Never a strike.
  • Pressing it again does nothing and never overwrites a reviewer's reason.

DELETE /v1/music/songs/{id} (the route still says DELETE but no longer deletes) · handler.go:1692-1742

Creator Restore

  • Only for the creator's own takedowns. On a reviewer takedown it is refused.
  • Returns the song to the state it had just before the takedown (published / review / draft). If that history is missing: published if it was ever public, otherwise draft.
  • Same song, so plays, likes and comments are all still there.

POST /v1/music/songs/{id}/restore · restore.go:71-162 · QC note "restore for creator takedown only" (restore.go:24)

Reviewer Takedown

  • Any admin. Reason must be copyright, violation or other (empty = other).
  • Works from published, review and draft.
  • Counts as a strike. Default note: "Violates the platform content policy".
  • After this the creator can neither restore nor delete the song, so the record of the violation stays.

POST /v1/music/admin/songs/{id}/takedown · moderation.go:195-249

Platform owner Undo a reviewer takedown

  • Only the one platform owner account (server setting HOOP_OWNER_UID). Reviewers and creators cannot. If no owner is set, nobody can.
  • Returns the song to its pre-takedown state, using the same rule as Restore, so an unapproved song is never pushed live by an undo.
  • The strike disappears on its own.
  • The creator gets a notice: "Your song X is back up — a review decision was reversed" (or "back in your studio" if it goes back to draft). It does not say who undid it.
  • Screen: Developer Centre → admin → "Reviewer takedowns (undo)".

GET /v1/music/admin/takedowns · POST …/undo-takedown · owner_undo.go:28-136 · decided by Haikal 09-29 ("platform owner", not the creator)

Creator Delete (permanent)

  • Only the song's creator. There is no admin delete.
  • Refused, in this order, if the song:
    1. has ever received a tip (the money trail must keep its song);
    2. is in a release that has ever been published;
    3. was taken down by a reviewer.
  • Otherwise it erases the audio for every version, the cover, and the song. Likes, favourites, comments, playlist entries, tags, collaborators and review history go with it.

DELETE /v1/music/songs/{id}/permanent · purge.go:56-153 · cascades: migrations 000145, 000148, 000216, 000226, 000227, 000255, 000256, 000267

Strikes and the upload ban

  • Strikes = the creator's songs that are currently removed by a reviewer.
  • 3 or more strikes → uploading audio is refused.
  • Because it counts current state, a restore or an owner undo removes the strike automatically.

handler.go:1476-1488 (count) · 2276-2280 (ban on upload)

④ Taking down a whole release (album / EP)

Decided by Haikal 09-29 ("option A"), live since v2.809.

POST /v1/music/releases/{id}/takedown · release_admin.go:249-426 · republish: release_api.go:523 · commit 77db18419

⑤ What each side sees

HOOP Music (listeners) when a song is removed

PlaceWhat happens
Browse, charts, related, "appears on", creator page, profile pin, Liked / FavouritesHidden (only published songs are listed)
Playing itOnly its creator and admins can still play it
A user's own playlistRow stays, marked "No longer available"; adding it again is refused
Room playlistRow stays but is hidden and skipped
Like, favourite, share, commentRefused: "This song has been taken down…"
Existing commentsListeners can no longer read them; the creator and admins still can. Nothing is deleted.

browse.go:90-190 · related.go:49 · appears_on.go:53,65 · creator_songs.go:55 · user_playlist.go:376-412,552-555 · playlist.go:25-32 · song_state_copy.go:28-33 · handler.go:2183-2195 · comments_removed_0929_db_test.go

Music Studio (creator) buttons

Song is…Status pillButtons
Published—Take It Down · Delete
Never published (draft / in review)—Delete
Taken down by the creatorTaken downRestore · Delete
Removed by a reviewerRemoved by reviewDelete is shown but will be refused (see gap 3 below); no Restore

The reason a reviewer gave appears in the song's review history.

music_studio_screen.dart:5164, 9161-9164, 9216-9269, 9437-9442 · song_edit_locks.dart:137-138 · strings en.json:2241-2263, 2468-2470

⑥ How the rules got here

WhenWhoWhat changed
07-12—Only hard delete existed
07-16—Admin takedown added
08-12Li MinThe creator's "delete" became a takedown: deleting lost tips and left ledger entries pointing at nothing. Only reviewer takedowns count as strikes.
08-23Li MinTwo separate buttons: "Take it down" vs "Delete is permanently delete it"; the three delete blockers
09-09LeongTake It Down hidden on songs that were never published
09-23 / 24QCTakedowns became restorable; removed songs' audio is frozen; "restore for creator takedown only"
09-29HaikalRelease takedown takes its songs down with it (option A, v2.809); comments on removed songs (v2.807); platform owner can undo a reviewer takedown (v2.814)

CHANGELOG.md:143-247, 6652-6711 · migrations 000215:1-10 · purge.go:11-19

⑦ Open points for Leong to decide

Found while reading the code. None is broken today, but each is a rule nobody has written down.

  1. Delete works on a live, published song if it has no tips and isn't in a published release. The Studio offers Delete next to Take It Down. Is permanently deleting a live single intended, or should it have to be taken down first?
  2. After a restore or owner undo, the old takedown reason stays on the song. Strikes are unaffected (they count current state), but the song's detail still carries the old reason and note.
  3. "Removed by review" songs still show a Delete button that the server will refuse. Should the button be hidden instead?
  4. Reviewer takedown also works on drafts, although the code comment says published / review only. Is striking a creator for a draft intended?
  5. The upload ban only blocks uploading audio. AI generation and publishing are not checked. Is that the intended scope of the ban?
  6. Two different meanings of "live release": the release cascade checks "currently published", while delete and restore check "was ever published". They can disagree for a release that was published and then taken down.
What has not been checked on a real screen: the owner undo screen and the status pills (per the CHANGELOG, v2.807 / v2.814). The phone app shows these only after the next TestFlight build; the web version already has them.