org.anthers.work
Schema Diff
+84 -1
Compatibility Analysis
Breaking Changes Detected
4 breaking changes, 25 non-breaking changes.
Breaking Changes (4)
- 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") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "org.anthers.work#namedContributor", src: "org.anthers.work#namedContributor", tgt: "org.anthers.work#namedContributor.name", kind: "prop", name: Some("name") }
- ConstraintTightened ConstraintTightened { vertex_id: "org.anthers.work:body.kind", sort: "knownValues", old_value: "[\"text\",\"video\",\"audio\",\"image\",\"ebook\",\"game\",\"software\",\"physical\",\"service\"]", new_value: "[\"text\",\"video\",\"music\",\"audio\",\"image\",\"comic\",\"ebook\",\"game\",\"software\",\"physical\",\"service\"]" }
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" }
Constraint Changes
- ConstraintTightened ConstraintTightened { vertex_id: "org.anthers.work:body.kind", sort: "knownValues", old_value: "[\"text\",\"video\",\"audio\",\"image\",\"ebook\",\"game\",\"software\",\"physical\",\"service\"]", new_value: "[\"text\",\"video\",\"music\",\"audio\",\"image\",\"comic\",\"ebook\",\"game\",\"software\",\"physical\",\"service\"]" }
Additional Notes
- 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") }
- Breaking: 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: 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
-
"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. This is an open set: consumers must accept values not listed here, because new mediums are added over time.",
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",
102
+
"music",
42
103
"audio",
43
104
"image",
105
+
"comic",
44
106
"ebook",
45
107
"game",
46
108
"software",
47
109
"physical",
48
110
"service"
49
111
],
50
112
"maxLength": 64,
51
113
"type": "string"
52
114
},
53
115
"releasedAt": {
54
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.",
55
117
"format": "datetime",
56
118
"type": "string"
57
119
},
58
120
"title": {
59
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.",
60
122
"maxGraphemes": 300,
61
123
"maxLength": 3000,
62
124
"type": "string"
63
125
},
64
126
"url": {
65
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.",
66
128
"format": "uri",
67
129
"type": "string"
68
130
}
69
131
},
70
132
"required": [
71
133
"kind",
72
134
"title",
73
135
"url",
74
136
"releasedAt"
75
137
],
76
138
"type": "object"
77
139
},
78
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"
79
162
}
80
163
},
81
164
"id": "org.anthers.work",
82
165
"lexicon": 1
83
166
}