org.anthers.work
Schema Diff
+81 -0
Compatibility Analysis
Breaking Changes Detected
3 breaking changes, 25 non-breaking changes.
Breaking Changes (3)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "org.anthers.work#namedContributor", src: "org.anthers.work#namedContributor", tgt: "org.anthers.work#namedContributor.name", kind: "prop", name: Some("name") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "org.anthers.work#credit", src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.types", kind: "prop", name: Some("types") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "org.anthers.work#didContributor", src: "org.anthers.work#didContributor", tgt: "org.anthers.work#didContributor.did", kind: "prop", name: Some("did") }
Non-Breaking Changes (25)
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.contributor" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.contributor:variant0" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.contributor:variant1" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.role" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.types" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#credit.types:items" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#didContributor" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#didContributor.did" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#namedContributor" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#namedContributor.name" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work#namedContributor.url" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work:body.credits" }
- AddedVertex AddedVertex { vertex_id: "org.anthers.work:body.credits:items" }
- AddedEdge AddedEdge { src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.contributor", kind: "prop", name: Some("contributor") }
- AddedEdge AddedEdge { src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.role", kind: "prop", name: Some("role") }
- AddedEdge AddedEdge { src: "org.anthers.work#credit.contributor", tgt: "org.anthers.work#credit.contributor:variant0", kind: "variant", name: Some("#didContributor") }
- AddedEdge AddedEdge { src: "org.anthers.work#credit.contributor", tgt: "org.anthers.work#credit.contributor:variant1", kind: "variant", name: Some("#namedContributor") }
- AddedEdge AddedEdge { src: "org.anthers.work#credit.contributor:variant0", tgt: "org.anthers.work#didContributor", kind: "ref", name: None }
- AddedEdge AddedEdge { src: "org.anthers.work#credit.contributor:variant1", tgt: "org.anthers.work#namedContributor", kind: "ref", name: None }
- AddedEdge AddedEdge { src: "org.anthers.work#credit.types", tgt: "org.anthers.work#credit.types:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "org.anthers.work#namedContributor", tgt: "org.anthers.work#namedContributor.url", kind: "prop", name: Some("url") }
- AddedEdge AddedEdge { src: "org.anthers.work:body", tgt: "org.anthers.work:body.credits", kind: "prop", name: Some("credits") }
- AddedEdge AddedEdge { src: "org.anthers.work:body.credits", tgt: "org.anthers.work:body.credits:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "org.anthers.work:body.credits:items", tgt: "org.anthers.work#credit", kind: "ref", name: None }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "org.anthers.work#credit" }AddedVertex { vertex_id: "org.anthers.work#credit.contributor" }AddedVertex { vertex_id: "org.anthers.work#credit.contributor:variant0" }AddedVertex { vertex_id: "org.anthers.work#credit.contributor:variant1" }AddedVertex { vertex_id: "org.anthers.work#credit.role" }AddedVertex { vertex_id: "org.anthers.work#credit.types" }AddedVertex { vertex_id: "org.anthers.work#credit.types:items" }AddedVertex { vertex_id: "org.anthers.work#didContributor" }AddedVertex { vertex_id: "org.anthers.work#didContributor.did" }AddedVertex { vertex_id: "org.anthers.work#namedContributor" }AddedVertex { vertex_id: "org.anthers.work#namedContributor.name" }AddedVertex { vertex_id: "org.anthers.work#namedContributor.url" }AddedVertex { vertex_id: "org.anthers.work:body.credits" }AddedVertex { vertex_id: "org.anthers.work:body.credits:items" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "org.anthers.work#didContributor", src: "org.anthers.work#didContributor", tgt: "org.anthers.work#didContributor.did", kind: "prop", name: Some("did") }
- Breaking: RequiredEdgeAdded { vertex_id: "org.anthers.work#namedContributor", src: "org.anthers.work#namedContributor", tgt: "org.anthers.work#namedContributor.name", kind: "prop", name: Some("name") }
- Breaking: RequiredEdgeAdded { vertex_id: "org.anthers.work#credit", src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.types", kind: "prop", name: Some("types") }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.contributor", kind: "prop", name: Some("contributor") }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit", tgt: "org.anthers.work#credit.role", kind: "prop", name: Some("role") }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit.contributor", tgt: "org.anthers.work#credit.contributor:variant0", kind: "variant", name: Some("#didContributor") }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit.contributor", tgt: "org.anthers.work#credit.contributor:variant1", kind: "variant", name: Some("#namedContributor") }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit.contributor:variant0", tgt: "org.anthers.work#didContributor", kind: "ref", name: None }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit.contributor:variant1", tgt: "org.anthers.work#namedContributor", kind: "ref", name: None }
- Non-breaking: AddedEdge { src: "org.anthers.work#credit.types", tgt: "org.anthers.work#credit.types:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "org.anthers.work#namedContributor", tgt: "org.anthers.work#namedContributor.url", kind: "prop", name: Some("url") }
- Non-breaking: AddedEdge { src: "org.anthers.work:body", tgt: "org.anthers.work:body.credits", kind: "prop", name: Some("credits") }
- Non-breaking: AddedEdge { src: "org.anthers.work:body.credits", tgt: "org.anthers.work:body.credits:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "org.anthers.work:body.credits:items", tgt: "org.anthers.work#credit", kind: "ref", name: None }
1
1
{
2
2
"$type": "com.atproto.lexicon.schema",
3
3
"defs": {
4
4
"access": {
5
5
"description": "Whether reaching this work costs anything. ⚠️ A display hint and NEVER an authorization: it describes what a stranger would find, not what any particular viewer is entitled to, and a consumer that treats it as permission is wrong. An object rather than a bare string so that further context — such as where access is granted — can be added later without a breaking change.",
6
6
"properties": {
7
7
"state": {
8
8
"description": "`open` — anyone may reach the work at no cost. `gated` — reaching it requires supporting the creator or buying it, on terms shown on the work's own page. Terms themselves are deliberately absent: a price shown apart from the total a person actually pays is misleading, and this record cannot control how a consumer renders it.",
9
9
"knownValues": [
10
10
"open",
11
11
"gated"
12
12
],
13
13
"maxLength": 32,
14
14
"type": "string"
15
15
}
16
16
},
17
17
"required": [
18
18
"state"
19
19
],
20
20
"type": "object"
21
21
},
22
+
"credit": {
23
+
"description": "One credit on the work: a contribution, its kind, and where a person made it, who. The three parts answer different questions and are kept apart so each can be absent on its own terms. `types` is the only required one — a credit must assert something.",
24
+
"properties": {
25
+
"contributor": {
26
+
"description": "Who is credited. A DID names an on-network identity and is withheld until that identity accepts (see `org.anthers.creditAcceptance`); a name names an off-network contributor and is published as entered. A union rather than a bare string or a single object, so a third contributor kind can join later as a permitted addition. Optional: a credit with no `created` among its types may name nobody — a license or a machine makes nothing a person owns. Required whenever `created` is among the types, alone or in a blend — anything a human made must name who.",
27
+
"refs": [
28
+
"#didContributor",
29
+
"#namedContributor"
30
+
],
31
+
"type": "union"
32
+
},
33
+
"role": {
34
+
"description": "The contribution this credit names, as a freeform title in the industry's own words — 'Written by', 'Cut by', 'Sound recording'. Freeform rather than a fixed list, because the useful roles differ by medium and a closed set would force every work into categories that fit none of them. Optional: a credit that is only a type assertion (a bare `ai` row, or an anonymous license) may leave the role unnamed.",
35
+
"maxGraphemes": 120,
36
+
"maxLength": 1200,
37
+
"type": "string"
38
+
},
39
+
"types": {
40
+
"description": "The kind(s) of contribution, published as entered. `created` — a person made this part. `licensed` — this part is pre-existing material used under a right (the source may be named or not, at the creator's choice; many licenses do not require attribution). `ai` — this part was machine-made: it records THAT it was, never which model, because a model owns nothing and can be granted nothing. An open set on purpose: a `created+ai` blend and the other non-empty subsets each mean what they say, and Anthers blesses no canonical 'counts as AI' reading of a blend — whether one clears a filter is the reader's own call, and two filters reading a blend opposite ways is a feature, not a defect.",
41
+
"items": {
42
+
"knownValues": [
43
+
"created",
44
+
"licensed",
45
+
"ai"
46
+
],
47
+
"maxLength": 16,
48
+
"type": "string"
49
+
},
50
+
"minLength": 1,
51
+
"type": "array"
52
+
}
53
+
},
54
+
"required": [
55
+
"types"
56
+
],
57
+
"type": "object"
58
+
},
59
+
"didContributor": {
60
+
"description": "A contributor identified by an on-network identity — their own DID. Naming one is a public claim about a third party, so it is withheld from the work record until that identity accepts it; an unconfirmed claim rendered as fact would travel somewhere a later correction cannot follow.",
61
+
"properties": {
62
+
"did": {
63
+
"description": "The contributor's DID.",
64
+
"format": "did",
65
+
"type": "string"
66
+
}
67
+
},
68
+
"required": [
69
+
"did"
70
+
],
71
+
"type": "object"
72
+
},
22
73
"main": {
23
74
"description": "One entry in a creator's Catalog — a game, video, album, essay, or other work they have released. This record is the public LISTING for that work: it says what the work is and where to reach it, and it never carries the work itself. It exists only while the work is publicly listed, and whether a particular person may open the work is decided by the service hosting it, never by this record.",
24
75
"key": "tid",
25
76
"record": {
26
77
"properties": {
27
78
"access": {
28
79
"ref": "#access",
29
80
"type": "ref"
30
81
},
82
+
"credits": {
83
+
"description": "Who made this work and what of it they made — the creator's own liner notes. Optional and additive: a work with no credits simply lists none, which says nothing against it (credits are asserted, never assumed). A credit naming an on-network identity by DID is withheld until that identity accepts it (see `org.anthers.creditAcceptance`), because a public claim about a third party should not be made in their name without their consent. The `types` flags are published exactly as the creator entered them — including `ai` — so a stranger can build a real filter on machine-made work.",
84
+
"items": {
85
+
"ref": "#credit",
86
+
"type": "ref"
87
+
},
88
+
"maxLength": 100,
89
+
"type": "array"
90
+
},
31
91
"description": {
32
92
"description": "The creator's own summary of the work. Plain text, so that every consumer can render it safely without a sanitizer.",
33
93
"maxGraphemes": 3000,
34
94
"maxLength": 30000,
35
95
"type": "string"
36
96
},
37
97
"kind": {
38
98
"description": "What sort of work this is, in the sense of how it is handled — which player or reader opens it. Named `kind` rather than `type` because a record already carries `$type`, and two differently-scoped `type` fields in one object is a needless trap for anyone reading the JSON. `comic` and `music` are narrower than `ebook` and `audio`, which mean a book that is not a comic and audio that is not music. This is an open set: consumers must accept values not listed here, because new mediums are added over time.",
39
99
"knownValues": [
40
100
"text",
41
101
"video",
42
102
"music",
43
103
"audio",
44
104
"image",
45
105
"comic",
46
106
"ebook",
47
107
"game",
48
108
"software",
49
109
"physical",
50
110
"service"
51
111
],
52
112
"maxLength": 64,
53
113
"type": "string"
54
114
},
55
115
"releasedAt": {
56
116
"description": "When the work was released to the public. This is the work's own date and the only one the record carries — record-creation time is already encoded in the record key, so a separate field for it would be a second, weaker answer to a question the key already answers.",
57
117
"format": "datetime",
58
118
"type": "string"
59
119
},
60
120
"title": {
61
121
"description": "The work's name, as its creator wrote it. Plain text for the same reason the description is: every consumer should be able to render it without a sanitizer. Required and never empty — a listing that names nothing is worse than no listing, so a work without a title is not published rather than published anonymously.",
62
122
"maxGraphemes": 300,
63
123
"maxLength": 3000,
64
124
"type": "string"
65
125
},
66
126
"url": {
67
127
"description": "Where this work can be reached. Usually its page on the service hosting it; a creator hosting their own Catalog points at their own. Deliberately not assumed to be an anthers.org address, because a creator's work outliving any one host is the point.",
68
128
"format": "uri",
69
129
"type": "string"
70
130
}
71
131
},
72
132
"required": [
73
133
"kind",
74
134
"title",
75
135
"url",
76
136
"releasedAt"
77
137
],
78
138
"type": "object"
79
139
},
80
140
"type": "record"
141
+
},
142
+
"namedContributor": {
143
+
"description": "A contributor with no network identity, named by the creator — an off-platform collaborator, or a source by title. Stays unconfirmed by construction: there is no actor who can accept.",
144
+
"properties": {
145
+
"name": {
146
+
"description": "The contributor or source, as the creator entered it.",
147
+
"maxGraphemes": 300,
148
+
"maxLength": 3000,
149
+
"type": "string"
150
+
},
151
+
"url": {
152
+
"description": "A link giving context — a portfolio, a source page.",
153
+
"format": "uri",
154
+
"maxLength": 2048,
155
+
"type": "string"
156
+
}
157
+
},
158
+
"required": [
159
+
"name"
160
+
],
161
+
"type": "object"
81
162
}
82
163
},
83
164
"id": "org.anthers.work",
84
165
"lexicon": 1
85
166
}