feat: add MusicTrack model and Story music-overlay fields

Schema groundwork for the Story music overlay: an admin-curated
MusicTrack catalog and three new optional Story fields (musicTrackId,
musicOffsetSecs, musicMuteOriginal). No user-upload path — licensing
liability stays with the admin who uploads a track.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Sonnet 5 committed 2026-09-14 19:59:42 +02:00
1 parent 0a9038a9a5
commit af0cea6d3f
1 file changed
+30 -2
+30 -2
View File
@@ -392,9 +392,37 @@ model Story {
reactions StoryReaction[]
comments StoryComment[]
// Story music overlay — optional, admin-curated catalog only (no user
// uploads, licensing liability). onDelete: SetNull so retiring/deleting a
// MusicTrack never orphans historical stories that already used it.
musicTrack MusicTrack? @relation(fields: [musicTrackId], references: [id], onDelete: SetNull)
musicTrackId String?
musicOffsetSecs Float? @default(0) // start point within the track, since story display duration is fixed
musicMuteOriginal Boolean @default(false) // VIDEO stories only — mute the baked-in Mux audio in favor of the track
@@index([petId, expiresAt]) // supports lazy-delete filter query
@@index([muxUploadId])
@@index([muxAssetId])
@@index([musicTrackId])
}
// Admin-curated royalty-free music catalog for the Story music overlay.
// Deliberately no user-upload path — copyright liability stays with the
// admin who uploads and records `licenseNote` for each track.
model MusicTrack {
id String @id @default(cuid())
title String @db.VarChar(100)
artist String @db.VarChar(100)
licenseNote String @db.VarChar(500) // license/source reference, required for compliance
storageKey String // Supabase Storage object key, MUSIC_STORAGE_BUCKET
durationSecs Float
active Boolean @default(true) // soft-disable instead of deleting so past stories keep working
createdBy String // ownerId of the admin who uploaded it
createdAt DateTime @default(now())
stories Story[]
@@index([active])
}
enum StoryMediaType {
@@ -855,8 +883,8 @@ model AdRepost {
model ModerationLog {
id String @id @default(cuid())
action String @db.VarChar(50) // DELETE_POST | DELETE_COMMENT | BAN_USER | UNBAN_USER | DELETE_IMAGE | DISMISS_REPORT | CREATE_AD | UPDATE_AD | DELETE_AD | GRANT_ROLE | REVOKE_ROLE | WARN_USER | VERIFY_PET | UNVERIFY_PET | DELETE_ACCOUNT | APPROVE_VERIFICATION_REQUEST | REJECT_VERIFICATION_REQUEST | HIDE_POST | UNHIDE_POST | SHADOWBAN_USER | UNSHADOWBAN_USER | SET_AI_DISCLOSURE | ENABLE_MAINTENANCE_MODE | DISABLE_MAINTENANCE_MODE | PIN_POST | UNPIN_POST | SEND_BROADCAST | DELETE_BROADCAST
targetType String @db.VarChar(20) // POST | COMMENT | USER | IMAGE | AD | REPORT | PET | SYSTEM
action String @db.VarChar(50) // DELETE_POST | DELETE_COMMENT | BAN_USER | UNBAN_USER | DELETE_IMAGE | DISMISS_REPORT | CREATE_AD | UPDATE_AD | DELETE_AD | GRANT_ROLE | REVOKE_ROLE | WARN_USER | VERIFY_PET | UNVERIFY_PET | DELETE_ACCOUNT | APPROVE_VERIFICATION_REQUEST | REJECT_VERIFICATION_REQUEST | HIDE_POST | UNHIDE_POST | SHADOWBAN_USER | UNSHADOWBAN_USER | SET_AI_DISCLOSURE | ENABLE_MAINTENANCE_MODE | DISABLE_MAINTENANCE_MODE | PIN_POST | UNPIN_POST | SEND_BROADCAST | DELETE_BROADCAST | CREATE_MUSIC_TRACK | UPDATE_MUSIC_TRACK | DELETE_MUSIC_TRACK
targetType String @db.VarChar(20) // POST | COMMENT | USER | IMAGE | AD | REPORT | PET | SYSTEM | MUSIC_TRACK
targetId String
reason String? @db.VarChar(500)
moderatorId String // ownerId