fm.freemix.track

lex-publisher.freemix.fm

Schema Diff

+5 -0

From

CID
bafyreia7arns5cf...
Indexed At
2026-07-26 20:07 UTC
View this version

To

CID
bafyreicnzvyoyam...
Indexed At
2026-08-24 00:23 UTC
View this version

Compatibility Analysis

Backward Compatible

Backward compatible. 2 non-breaking changes.

Non-Breaking Changes (2)
  • AddedVertex AddedVertex { vertex_id: "fm.freemix.track:body.artworkSeed" }
  • AddedEdge AddedEdge { src: "fm.freemix.track:body", tgt: "fm.freemix.track:body.artworkSeed", kind: "prop", name: Some("artworkSeed") }

Migration Guidance

Added Elements

  • AddedVertex { vertex_id: "fm.freemix.track:body.artworkSeed" }

Additional Notes

  • Non-breaking: AddedEdge { src: "fm.freemix.track:body", tgt: "fm.freemix.track:body.artworkSeed", kind: "prop", name: Some("artworkSeed") }
1 1
{
2 2
  "id": "fm.freemix.track",
3 3
  "defs": {
4 4
    "main": {
5 5
      "key": "tid",
6 6
      "type": "record",
7 7
      "record": {
8 8
        "type": "object",
9 9
        "required": [
10 10
          "title",
11 11
          "artist",
12 12
          "audioHash",
13 13
          "audioFormat",
14 14
          "audioSizeBytes",
15 15
          "license",
16 16
          "createdAt"
17 17
        ],
18 18
        "properties": {
19 19
          "key": {
20 20
            "type": "string",
21 21
            "maxLength": 10,
22 22
            "description": "Musical key (e.g., 'Am', 'F#m', 'Bb')"
23 23
          },
24 24
          "isrc": {
25 25
            "type": "string",
26 26
            "maxLength": 15,
27 27
            "description": "International Standard Recording Code (this recording). MIGRATED from the old top-level `isrc` field (FM-549 s41); existing records carrying top-level isrc are relocated here by the T3 data migration."
28 28
          },
29 29
          "iswc": {
30 30
            "type": "string",
31 31
            "maxLength": 15,
32 32
            "description": "International Standard Musical Work Code (the composition). FM-550."
33 33
          },
34 34
          "tags": {
35 35
            "type": "array",
36 36
            "items": {
37 37
              "type": "string",
38 38
              "maxLength": 50
39 39
            },
40 40
            "maxLength": 10,
41 41
            "description": "Freeform tags"
42 42
          },
43 43
          "genre": {
44 44
            "type": "array",
45 45
            "items": {
46 46
              "type": "string",
47 47
              "maxLength": 50
48 48
            },
49 49
            "maxLength": 5,
50 50
            "description": "Genre classifications"
51 51
          },
52 52
          "title": {
53 53
            "type": "string",
54 54
            "maxLength": 300,
55 55
            "description": "Track title"
56 56
          },
57 57
          "artist": {
58 58
            "type": "string",
59 59
            "maxLength": 200,
60 60
            "description": "Artist name"
61 61
          },
62 62
          "seller": {
63 63
            "type": "string",
64 64
            "format": "did",
65 65
            "description": "parties.seller (s39): the single account DID that owns and sells this item (owner = seller = uploader; may be an org account). Charge/entitlement read THIS field. One-field indirection from record author. INLINE — keep in sync."
66 66
          },
67 67
          "buyLink": {
68 68
            "type": "string",
69 69
            "format": "uri",
70 70
            "maxLength": 500,
71 71
            "description": "URL to purchase or stream (Bandcamp, Beatport, Spotify, etc.)"
72 72
          },
73 73
          "clipUrl": {
74 74
            "type": "string",
75 75
            "format": "uri",
76 76
            "maxLength": 3000,
77 77
            "description": "FM-508: public URL to a short (~30s) truncated audio clip — the record's only public audio artifact. Tracks only; stems and samples never carry a clip. Optional."
78 78
          },
79 79
          "credits": {
80 80
            "type": "array",
81 81
            "items": {
82 82
              "type": "object",
83 83
              "required": [
84 84
                "role",
85 85
                "name"
86 86
              ],
87 87
              "properties": {
88 88
                "did": {
89 89
                  "type": "string",
90 90
                  "format": "did",
91 91
                  "description": "ATProto identity of the credited party, when on-network. OPTIONAL and load-bearing — named-but-unlinked credits are the common case."
92 92
                },
93 93
                "ipi": {
94 94
                  "type": "string",
95 95
                  "maxLength": 20,
96 96
                  "description": "IPI/CAE number for PRO reconciliation. Optional."
97 97
                },
98 98
                "name": {
99 99
                  "type": "string",
100 100
                  "maxLength": 256,
101 101
                  "description": "Credited party's name. Required. Works for off-network parties (sampled composer, session player) with no ATProto identity.",
102 102
                  "maxGraphemes": 128
103 103
                },
104 104
                "role": {
105 105
                  "type": "string",
106 106
                  "maxLength": 64,
107 107
                  "description": "Credit role. OPEN knownValues (not a closed enum) — off-list roles allowed without a lexicon bump; the list is UI-picker guidance.",
108 108
                  "knownValues": [
109 109
                    "composer",
110 110
                    "lyricist",
111 111
                    "composerLyricist",
112 112
                    "writer",
113 113
                    "arranger",
114 114
                    "adapter",
115 115
                    "translator",
116 116
                    "performer",
117 117
                    "featuredArtist",
118 118
                    "vocalist",
119 119
                    "producer",
120 120
                    "remixer",
121 121
                    "mixEngineer",
122 122
                    "masteringEngineer",
123 123
                    "sampledArtist",
124 124
                    "originalArtist"
125 125
                  ]
126 126
                }
127 127
              }
128 128
            },
129 129
            "maxLength": 64,
130 130
            "description": "Descriptive credit lines (FM-550). Repeatable; multiple entries may share a role. Record-of-fact only — read by NO money/control code (s41). PRO-registration shape, not a split sheet: no percentages, no payout fields."
131 131
          },
132 132
          "license": {
133 133
            "type": "string",
134 134
            "format": "at-uri",
135 135
            "maxLength": 3000,
136 136
            "description": "AT URI to the license grant record"
137 137
          },
138 138
          "audioUrl": {
139 139
            "type": "string",
140 140
            "format": "uri",
141 141
            "maxLength": 3000,
142 142
            "description": "DEPRECATED (FM-508): no longer emitted. Full-quality audio is private (gated download only) and is never surfaced in the portable record. Field kept (optional) to tolerate pre-FM-508 records without a putRecord rewrite."
143 143
          },
144 144
          "currency": {
145 145
            "type": "string",
146 146
            "maxLength": 3,
147 147
            "description": "ISO-4217 currency code. Phase 1 = USD only. INLINE sellability shape — keep in sync across sellable types.",
148 148
            "knownValues": [
149 149
              "USD"
150 150
            ]
151 151
          },
152 152
          "audioHash": {
153 153
            "type": "string",
154 154
            "maxLength": 200,
155 155
            "description": "SHA-256 hash of the audio file content"
156 156
          },
157 157
          "bpmCentis": {
158 158
            "type": "integer",
159 159
            "maximum": 99900,
160 160
            "minimum": 2000,
161 161
            "description": "Beats per minute in centiBPM (multiply actual BPM by 100, e.g., 174.50 BPM = 17450)"
162 162
          },
163 163
          "createdAt": {
164 164
            "type": "string",
165 165
            "format": "datetime",
166 166
            "maxLength": 100,
167 167
            "description": "Record creation timestamp"
168 168
          },
169 169
          "isReleased": {
170 170
            "type": "boolean",
171 171
            "description": "Whether this track was previously released outside FreeMix"
172 172
          },
173 173
          "priceCents": {
174 174
            "type": "integer",
175 175
            "minimum": 0,
176 176
            "description": "On-network price in integer cents (FM-549: price goes on-network; offer is public, sale is private). 0 or absent = free. Hard price floor enforced in app, not schema. INLINE sellability shape — authored identically in fm.freemix.release and fm.freemix.group.stemsGroup; keep in sync (s41)."
177 177
          },
178 178
          "stemAccess": {
179 179
            "type": "string",
180 180
            "maxLength": 100,
181 181
            "description": "Who can access stems. Defaults to 'open'. Phase 1 only supports 'open' and 'community'.",
182 182
            "knownValues": [
183 183
              "open",
184 184
              "community",
185 185
              "request",
186 186
              "pro"
187 187
            ]
188 188
          },
189 +
          "artworkSeed": {
190 +
            "type": "string",
191 +
            "maxLength": 384,
192 +
            "description": "FM-729: seed the generative cover placeholder is drawn from. Grammar \"<title>#deck<gen>#regen<n>\"; both counters recompute from this one string, so there are no separate deck/attempt fields. Optional - absent means fall back to the title (the pre-FM-729 implicit seed), which renders the existing cover unchanged. Never an empty string (an empty seed is a fixed point of the generator's LCG and collapses the art). Kept on the record even when coverArtUrl is set, so removing an uploaded cover restores the same generated art. maxLength 384 = title's 300 plus suffix headroom."
193 +
          },
189 194
          "audioFormat": {
190 195
            "type": "string",
191 196
            "maxLength": 100,
192 197
            "description": "Audio file format",
193 198
            "knownValues": [
194 199
              "wav",
195 200
              "flac",
196 201
              "mp3",
197 202
              "aac",
198 203
              "ogg",
199 204
              "aiff"
200 205
            ]
201 206
          },
202 207
          "coverArtUrl": {
203 208
            "type": "string",
204 209
            "format": "uri",
205 210
            "maxLength": 3000,
206 211
            "description": "URL to cover art image"
207 212
          },
208 213
          "description": {
209 214
            "type": "string",
210 215
            "maxLength": 5000,
211 216
            "description": "Track description"
212 217
          },
213 218
          "releaseDate": {
214 219
            "type": "string",
215 220
            "format": "datetime",
216 221
            "description": "Original release date (ISO 8601)"
217 222
          },
218 223
          "coverArtHash": {
219 224
            "type": "string",
220 225
            "maxLength": 200,
221 226
            "description": "SHA-256 hash of the cover art"
222 227
          },
223 228
          "releaseLabel": {
224 229
            "type": "string",
225 230
            "maxLength": 255,
226 231
            "description": "Label name (e.g., 'Vizual Records', 'self-released')"
227 232
          },
228 233
          "aiDeclaration": {
229 234
            "type": "object",
230 235
            "required": [
231 236
              "category"
232 237
            ],
233 238
            "properties": {
234 239
              "tools": {
235 240
                "type": "array",
236 241
                "items": {
237 242
                  "type": "string",
238 243
                  "maxLength": 100
239 244
                },
240 245
                "maxLength": 10,
241 246
                "description": "AI tools used"
242 247
              },
243 248
              "category": {
244 249
                "type": "string",
245 250
                "maxLength": 100,
246 251
                "description": "Level of AI involvement",
247 252
                "knownValues": [
248 253
                  "none",
249 254
                  "assisted",
250 255
                  "augmented",
251 256
                  "generated"
252 257
                ]
253 258
              },
254 259
              "description": {
255 260
                "type": "string",
256 261
                "maxLength": 1000,
257 262
                "description": "Creator's description of how AI was used"
258 263
              }
259 264
            },
260 265
            "description": "Declaration of AI involvement in creation"
261 266
          },
262 267
          "catalogNumber": {
263 268
            "type": "string",
264 269
            "maxLength": 100,
265 270
            "description": "Catalog number (e.g., 'VIZ-042')"
266 271
          },
267 272
          "audioSizeBytes": {
268 273
            "type": "integer",
269 274
            "description": "Size of the audio file in bytes"
270 275
          },
271 276
          "audioDurationMs": {
272 277
            "type": "integer",
273 278
            "description": "Duration of the track in milliseconds"
274 279
          },
275 280
          "derivativeSubType": {
276 281
            "type": "string",
277 282
            "maxLength": 100,
278 283
            "description": "The derivative kind for Remix/Edit/Mashup uploads. Absent on Original tracks. Durable provenance — the authoritative signal that a track is a derivative, independent of source count. knownValues (not a closed enum) so future subtypes don't break existing records.",
279 284
            "knownValues": [
280 285
              "remix",
281 286
              "edit",
282 287
              "mashup"
283 288
            ]
284 289
          },
285 290
          "copyrightRecording": {
286 291
            "type": "string",
287 292
            "maxLength": 256,
288 293
            "description": "℗ line for the sound recording, e.g. '2026 <label>'. FM-550. NOTE: label rides here + the Previously-Released fields, NOT the credits role vocabulary (s41).",
289 294
            "maxGraphemes": 128
290 295
          },
291 296
          "copyrightComposition": {
292 297
            "type": "string",
293 298
            "maxLength": 256,
294 299
            "description": "© line for the composition, e.g. '2026 Joshua Michaels'. FM-550.",
295 300
            "maxGraphemes": 128
296 301
          },
297 302
          "noAttributableSourcesAttested": {
298 303
            "type": "boolean",
299 304
            "description": "True only when the uploader affirmed via the upload UI that this derivative has no FreeMix-attributable source (own work, licensed, off-platform, or since-deleted). Never set automatically from source count — it is an explicit human attestation, not a computed value."
300 305
          }
301 306
        }
302 307
      },
303 308
      "description": "A music track record on FreeMix. Top-level leaf (FM-549 s38: pulled out from under the release.* prefix; release.track -> track)."
304 309
    }
305 310
  },
306 311
  "$type": "com.atproto.lexicon.schema",
307 312
  "lexicon": 1
308 313
}

Compare Other Versions

Lexicon Garden

@