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
  "$type": "com.atproto.lexicon.schema",
3 3
  "defs": {
4 4
    "main": {
5 5
      "description": "A music track record on FreeMix. Top-level leaf (FM-549 s38: pulled out from under the release.* prefix; release.track -> track).",
6 6
      "key": "tid",
7 7
      "record": {
8 8
        "properties": {
9 9
          "aiDeclaration": {
10 10
            "description": "Declaration of AI involvement in creation",
11 11
            "properties": {
12 12
              "category": {
13 13
                "description": "Level of AI involvement",
14 14
                "knownValues": [
15 15
                  "none",
16 16
                  "assisted",
17 17
                  "augmented",
18 18
                  "generated"
19 19
                ],
20 20
                "maxLength": 100,
21 21
                "type": "string"
22 22
              },
23 23
              "description": {
24 24
                "description": "Creator's description of how AI was used",
25 25
                "maxLength": 1000,
26 26
                "type": "string"
27 27
              },
28 28
              "tools": {
29 29
                "description": "AI tools used",
30 30
                "items": {
31 31
                  "maxLength": 100,
32 32
                  "type": "string"
33 33
                },
34 34
                "maxLength": 10,
35 35
                "type": "array"
36 36
              }
37 37
            },
38 38
            "required": [
39 39
              "category"
40 40
            ],
41 41
            "type": "object"
42 42
          },
43 43
          "artist": {
44 44
            "description": "Artist name",
45 45
            "maxLength": 200,
46 46
            "type": "string"
47 47
          },
48 +
          "artworkSeed": {
49 +
            "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.",
50 +
            "maxLength": 384,
51 +
            "type": "string"
52 +
          },
48 53
          "audioDurationMs": {
49 54
            "description": "Duration of the track in milliseconds",
50 55
            "type": "integer"
51 56
          },
52 57
          "audioFormat": {
53 58
            "description": "Audio file format",
54 59
            "knownValues": [
55 60
              "wav",
56 61
              "flac",
57 62
              "mp3",
58 63
              "aac",
59 64
              "ogg",
60 65
              "aiff"
61 66
            ],
62 67
            "maxLength": 100,
63 68
            "type": "string"
64 69
          },
65 70
          "audioHash": {
66 71
            "description": "SHA-256 hash of the audio file content",
67 72
            "maxLength": 200,
68 73
            "type": "string"
69 74
          },
70 75
          "audioSizeBytes": {
71 76
            "description": "Size of the audio file in bytes",
72 77
            "type": "integer"
73 78
          },
74 79
          "audioUrl": {
75 80
            "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.",
76 81
            "format": "uri",
77 82
            "maxLength": 3000,
78 83
            "type": "string"
79 84
          },
80 85
          "bpmCentis": {
81 86
            "description": "Beats per minute in centiBPM (multiply actual BPM by 100, e.g., 174.50 BPM = 17450)",
82 87
            "maximum": 99900,
83 88
            "minimum": 2000,
84 89
            "type": "integer"
85 90
          },
86 91
          "buyLink": {
87 92
            "description": "URL to purchase or stream (Bandcamp, Beatport, Spotify, etc.)",
88 93
            "format": "uri",
89 94
            "maxLength": 500,
90 95
            "type": "string"
91 96
          },
92 97
          "catalogNumber": {
93 98
            "description": "Catalog number (e.g., 'VIZ-042')",
94 99
            "maxLength": 100,
95 100
            "type": "string"
96 101
          },
97 102
          "clipUrl": {
98 103
            "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.",
99 104
            "format": "uri",
100 105
            "maxLength": 3000,
101 106
            "type": "string"
102 107
          },
103 108
          "copyrightComposition": {
104 109
            "description": "© line for the composition, e.g. '2026 Joshua Michaels'. FM-550.",
105 110
            "maxGraphemes": 128,
106 111
            "maxLength": 256,
107 112
            "type": "string"
108 113
          },
109 114
          "copyrightRecording": {
110 115
            "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).",
111 116
            "maxGraphemes": 128,
112 117
            "maxLength": 256,
113 118
            "type": "string"
114 119
          },
115 120
          "coverArtHash": {
116 121
            "description": "SHA-256 hash of the cover art",
117 122
            "maxLength": 200,
118 123
            "type": "string"
119 124
          },
120 125
          "coverArtUrl": {
121 126
            "description": "URL to cover art image",
122 127
            "format": "uri",
123 128
            "maxLength": 3000,
124 129
            "type": "string"
125 130
          },
126 131
          "createdAt": {
127 132
            "description": "Record creation timestamp",
128 133
            "format": "datetime",
129 134
            "maxLength": 100,
130 135
            "type": "string"
131 136
          },
132 137
          "credits": {
133 138
            "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.",
134 139
            "items": {
135 140
              "properties": {
136 141
                "did": {
137 142
                  "description": "ATProto identity of the credited party, when on-network. OPTIONAL and load-bearing — named-but-unlinked credits are the common case.",
138 143
                  "format": "did",
139 144
                  "type": "string"
140 145
                },
141 146
                "ipi": {
142 147
                  "description": "IPI/CAE number for PRO reconciliation. Optional.",
143 148
                  "maxLength": 20,
144 149
                  "type": "string"
145 150
                },
146 151
                "name": {
147 152
                  "description": "Credited party's name. Required. Works for off-network parties (sampled composer, session player) with no ATProto identity.",
148 153
                  "maxGraphemes": 128,
149 154
                  "maxLength": 256,
150 155
                  "type": "string"
151 156
                },
152 157
                "role": {
153 158
                  "description": "Credit role. OPEN knownValues (not a closed enum) — off-list roles allowed without a lexicon bump; the list is UI-picker guidance.",
154 159
                  "knownValues": [
155 160
                    "composer",
156 161
                    "lyricist",
157 162
                    "composerLyricist",
158 163
                    "writer",
159 164
                    "arranger",
160 165
                    "adapter",
161 166
                    "translator",
162 167
                    "performer",
163 168
                    "featuredArtist",
164 169
                    "vocalist",
165 170
                    "producer",
166 171
                    "remixer",
167 172
                    "mixEngineer",
168 173
                    "masteringEngineer",
169 174
                    "sampledArtist",
170 175
                    "originalArtist"
171 176
                  ],
172 177
                  "maxLength": 64,
173 178
                  "type": "string"
174 179
                }
175 180
              },
176 181
              "required": [
177 182
                "role",
178 183
                "name"
179 184
              ],
180 185
              "type": "object"
181 186
            },
182 187
            "maxLength": 64,
183 188
            "type": "array"
184 189
          },
185 190
          "currency": {
186 191
            "description": "ISO-4217 currency code. Phase 1 = USD only. INLINE sellability shape — keep in sync across sellable types.",
187 192
            "knownValues": [
188 193
              "USD"
189 194
            ],
190 195
            "maxLength": 3,
191 196
            "type": "string"
192 197
          },
193 198
          "derivativeSubType": {
194 199
            "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.",
195 200
            "knownValues": [
196 201
              "remix",
197 202
              "edit",
198 203
              "mashup"
199 204
            ],
200 205
            "maxLength": 100,
201 206
            "type": "string"
202 207
          },
203 208
          "description": {
204 209
            "description": "Track description",
205 210
            "maxLength": 5000,
206 211
            "type": "string"
207 212
          },
208 213
          "genre": {
209 214
            "description": "Genre classifications",
210 215
            "items": {
211 216
              "maxLength": 50,
212 217
              "type": "string"
213 218
            },
214 219
            "maxLength": 5,
215 220
            "type": "array"
216 221
          },
217 222
          "isReleased": {
218 223
            "description": "Whether this track was previously released outside FreeMix",
219 224
            "type": "boolean"
220 225
          },
221 226
          "isrc": {
222 227
            "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.",
223 228
            "maxLength": 15,
224 229
            "type": "string"
225 230
          },
226 231
          "iswc": {
227 232
            "description": "International Standard Musical Work Code (the composition). FM-550.",
228 233
            "maxLength": 15,
229 234
            "type": "string"
230 235
          },
231 236
          "key": {
232 237
            "description": "Musical key (e.g., 'Am', 'F#m', 'Bb')",
233 238
            "maxLength": 10,
234 239
            "type": "string"
235 240
          },
236 241
          "license": {
237 242
            "description": "AT URI to the license grant record",
238 243
            "format": "at-uri",
239 244
            "maxLength": 3000,
240 245
            "type": "string"
241 246
          },
242 247
          "noAttributableSourcesAttested": {
243 248
            "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.",
244 249
            "type": "boolean"
245 250
          },
246 251
          "priceCents": {
247 252
            "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).",
248 253
            "minimum": 0,
249 254
            "type": "integer"
250 255
          },
251 256
          "releaseDate": {
252 257
            "description": "Original release date (ISO 8601)",
253 258
            "format": "datetime",
254 259
            "type": "string"
255 260
          },
256 261
          "releaseLabel": {
257 262
            "description": "Label name (e.g., 'Vizual Records', 'self-released')",
258 263
            "maxLength": 255,
259 264
            "type": "string"
260 265
          },
261 266
          "seller": {
262 267
            "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.",
263 268
            "format": "did",
264 269
            "type": "string"
265 270
          },
266 271
          "stemAccess": {
267 272
            "description": "Who can access stems. Defaults to 'open'. Phase 1 only supports 'open' and 'community'.",
268 273
            "knownValues": [
269 274
              "open",
270 275
              "community",
271 276
              "request",
272 277
              "pro"
273 278
            ],
274 279
            "maxLength": 100,
275 280
            "type": "string"
276 281
          },
277 282
          "tags": {
278 283
            "description": "Freeform tags",
279 284
            "items": {
280 285
              "maxLength": 50,
281 286
              "type": "string"
282 287
            },
283 288
            "maxLength": 10,
284 289
            "type": "array"
285 290
          },
286 291
          "title": {
287 292
            "description": "Track title",
288 293
            "maxLength": 300,
289 294
            "type": "string"
290 295
          }
291 296
        },
292 297
        "required": [
293 298
          "title",
294 299
          "artist",
295 300
          "audioHash",
296 301
          "audioFormat",
297 302
          "audioSizeBytes",
298 303
          "license",
299 304
          "createdAt"
300 305
        ],
301 306
        "type": "object"
302 307
      },
303 308
      "type": "record"
304 309
    }
305 310
  },
306 311
  "id": "fm.freemix.track",
307 312
  "lexicon": 1
308 313
}

Compare Other Versions

Lexicon Garden

@