at.eptss.candidateLedger

eptss.at

Schema Diff

+20 -23

From

CID
bafyreiho7e3g6df...
Indexed At
2026-08-01 05:41 UTC
View this version

To

CID
bafyreidjztfzp6u...
Indexed At
2026-08-10 04:16 UTC
View this version

Compatibility Analysis

Breaking Changes Detected

18 breaking changes, 9 non-breaking changes.

Breaking Changes (18)
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.playlist", kind: "prop", name: Some("playlist") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.nominations", kind: "prop", name: Some("nominations") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger#nomination", src: "at.eptss.candidateLedger#nomination", tgt: "at.eptss.candidateLedger#nomination.by", kind: "prop", name: Some("by") }
  • RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger#nomination", src: "at.eptss.candidateLedger#nomination", tgt: "at.eptss.candidateLedger#nomination.track", kind: "prop", name: Some("track") }
  • RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger#candidate", src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.title", kind: "prop", name: Some("title") }
  • RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger#candidate", src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.artist", kind: "prop", name: Some("artist") }
  • RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.candidates", kind: "prop", name: Some("candidates") }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.artist" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.listenLink" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.nominatedBy" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.title" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger:body.candidates" }
  • RemovedVertex RemovedVertex { vertex_id: "at.eptss.candidateLedger:body.candidates:items" }
  • RemovedEdge RemovedEdge { src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.listenLink", kind: "prop", name: Some("listenLink") }
  • RemovedEdge RemovedEdge { src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.nominatedBy", kind: "prop", name: Some("nominatedBy") }
  • RemovedEdge RemovedEdge { src: "at.eptss.candidateLedger:body.candidates", tgt: "at.eptss.candidateLedger:body.candidates:items", kind: "items", name: None }
  • RemovedEdge RemovedEdge { src: "at.eptss.candidateLedger:body.candidates:items", tgt: "at.eptss.candidateLedger#candidate", kind: "ref", name: None }
Non-Breaking Changes (9)
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination" }
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination.by" }
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination.track" }
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger:body.nominations" }
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger:body.nominations:items" }
  • AddedVertex AddedVertex { vertex_id: "at.eptss.candidateLedger:body.playlist" }
  • AddedEdge AddedEdge { src: "at.eptss.candidateLedger:body.nominations", tgt: "at.eptss.candidateLedger:body.nominations:items", kind: "items", name: None }
  • AddedEdge AddedEdge { src: "at.eptss.candidateLedger:body.nominations:items", tgt: "at.eptss.candidateLedger#nomination", kind: "ref", name: None }
  • AddedEdge AddedEdge { src: "at.eptss.candidateLedger:body.playlist", tgt: "com.atproto.repo.strongRef", kind: "ref", name: None }

Migration Guidance

Removed Elements

  • RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.artist" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.listenLink" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.nominatedBy" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger#candidate.title" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger:body.candidates" }
  • RemovedVertex { vertex_id: "at.eptss.candidateLedger:body.candidates:items" }

Added Elements

  • AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination" }
  • AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination.by" }
  • AddedVertex { vertex_id: "at.eptss.candidateLedger#nomination.track" }
  • AddedVertex { vertex_id: "at.eptss.candidateLedger:body.nominations" }
  • AddedVertex { vertex_id: "at.eptss.candidateLedger:body.nominations:items" }
  • AddedVertex { vertex_id: "at.eptss.candidateLedger:body.playlist" }

Additional Notes

  • Breaking: RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.playlist", kind: "prop", name: Some("playlist") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.nominations", kind: "prop", name: Some("nominations") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger#nomination", src: "at.eptss.candidateLedger#nomination", tgt: "at.eptss.candidateLedger#nomination.by", kind: "prop", name: Some("by") }
  • Breaking: RequiredEdgeAdded { vertex_id: "at.eptss.candidateLedger#nomination", src: "at.eptss.candidateLedger#nomination", tgt: "at.eptss.candidateLedger#nomination.track", kind: "prop", name: Some("track") }
  • Breaking: RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger:body", src: "at.eptss.candidateLedger:body", tgt: "at.eptss.candidateLedger:body.candidates", kind: "prop", name: Some("candidates") }
  • Breaking: RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger#candidate", src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.title", kind: "prop", name: Some("title") }
  • Breaking: RequiredEdgeRemoved { vertex_id: "at.eptss.candidateLedger#candidate", src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.artist", kind: "prop", name: Some("artist") }
  • Breaking: RemovedEdge { src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.listenLink", kind: "prop", name: Some("listenLink") }
  • Breaking: RemovedEdge { src: "at.eptss.candidateLedger#candidate", tgt: "at.eptss.candidateLedger#candidate.nominatedBy", kind: "prop", name: Some("nominatedBy") }
  • Breaking: RemovedEdge { src: "at.eptss.candidateLedger:body.candidates", tgt: "at.eptss.candidateLedger:body.candidates:items", kind: "items", name: None }
  • Breaking: RemovedEdge { src: "at.eptss.candidateLedger:body.candidates:items", tgt: "at.eptss.candidateLedger#candidate", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.eptss.candidateLedger:body.nominations", tgt: "at.eptss.candidateLedger:body.nominations:items", kind: "items", name: None }
  • Non-breaking: AddedEdge { src: "at.eptss.candidateLedger:body.nominations:items", tgt: "at.eptss.candidateLedger#nomination", kind: "ref", name: None }
  • Non-breaking: AddedEdge { src: "at.eptss.candidateLedger:body.playlist", tgt: "com.atproto.repo.strongRef", kind: "ref", name: None }
1 1
{
2 2
  "id": "at.eptss.candidateLedger",
3 3
  "defs": {
4 4
    "main": {
5 5
      "key": "any",
6 6
      "type": "record",
7 7
      "record": {
8 8
        "type": "object",
9 9
        "required": [
10 10
          "round",
11 -
          "candidates",
11 +
          "playlist",
12 +
          "nominations",
12 13
          "publishedAt"
13 14
        ],
14 15
        "properties": {
15 16
          "round": {
16 17
            "ref": "com.atproto.repo.strongRef",
17 18
            "type": "ref",
18 19
            "description": "The at.atjam.round this ledger belongs to."
19 20
          },
20 -
          "candidates": {
21 +
          "playlist": {
22 +
            "ref": "com.atproto.repo.strongRef",
23 +
            "type": "ref",
24 +
            "description": "The at.atjam.playlist holding the candidates, in ballot order, CID-pinned."
25 +
          },
26 +
          "nominations": {
21 27
            "type": "array",
22 28
            "items": {
23 -
              "ref": "#candidate",
29 +
              "ref": "#nomination",
24 30
              "type": "ref"
25 31
            },
26 32
            "maxLength": 256,
27 -
            "minLength": 1
33 +
            "description": "Who put what in the hat. Empty when every candidate was organizer-carried. Tracks absent here are carried candidates, unattributed by design."
28 34
          },
29 35
          "publishedAt": {
30 36
            "type": "string",
31 37
            "format": "datetime"
32 38
          }
33 39
        }
34 40
      },
35 -
      "description": "The round's ballot sheet: every nominated song, revealed as one atomic record when signups close. Published by the round organizer. nominatedBy links a candidate to its nominator; entries carried over by an organizer omit it. The organizer is responsible for honoring un-naming requests by editing this record in place."
41 +
      "description": "The round's ballot sheet, revealed as one atomic record when signups close. Published by the round organizer. The candidate list itself lives in an at.atjam.playlist of at.eptss.track records — this record pins that playlist by CID and adds only what a playlist must never carry: round attribution and who nominated what. Ballots strong-ref this ledger, so the pin chain runs ballot → ledger → playlist → tracks, and a post-hoc edit anywhere is detectable. Attribution keys on the track's AT-URI, never on its position — a positional array desyncs silently on one reorder. The organizer honors un-naming requests by editing nominations in place."
36 42
    },
37 -
    "candidate": {
43 +
    "nomination": {
38 44
      "type": "object",
39 45
      "required": [
40 -
        "title",
41 -
        "artist"
46 +
        "track",
47 +
        "by"
42 48
      ],
43 49
      "properties": {
44 -
        "title": {
45 -
          "type": "string",
46 -
          "maxLength": 5120,
47 -
          "maxGraphemes": 512
48 -
        },
49 -
        "artist": {
50 -
          "type": "string",
51 -
          "maxLength": 5120,
52 -
          "maxGraphemes": 512
53 -
        },
54 -
        "listenLink": {
50 +
        "by": {
55 51
          "type": "string",
56 -
          "format": "uri"
52 +
          "format": "did",
53 +
          "description": "DID of the member who nominated it."
57 54
        },
58 -
        "nominatedBy": {
55 +
        "track": {
59 56
          "type": "string",
60 -
          "format": "did",
61 -
          "description": "DID of the member who nominated this song. Absent for organizer-carried candidates."
57 +
          "format": "at-uri",
58 +
          "description": "The at.eptss.track this attribution is about. A URI and not an index: identity, not position."
62 59
        }
63 60
      }
64 61
    }
65 62
  },
66 63
  "$type": "com.atproto.lexicon.schema",
67 64
  "lexicon": 1
68 65
}

Compare Other Versions

Lexicon Garden

@