fyi.atstore.listing.detail
Schema Diff
+50 -1
Compatibility Analysis
Breaking Changes Detected
3 breaking changes, 10 non-breaking changes.
Breaking Changes (3)
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "fyi.atstore.listing.detail#link", src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.url", kind: "prop", name: Some("url") }
- RequiredEdgeAdded RequiredEdgeAdded { vertex_id: "fyi.atstore.listing.detail#link", src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.type", kind: "prop", name: Some("type") }
- RequiredEdgeRemoved RequiredEdgeRemoved { vertex_id: "fyi.atstore.listing.detail:body", src: "fyi.atstore.listing.detail:body", tgt: "fyi.atstore.listing.detail:body.heroImage", kind: "prop", name: Some("heroImage") }
Non-Breaking Changes (10)
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail#link" }
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.label" }
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.type" }
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.url" }
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail:body.links" }
- AddedVertex AddedVertex { vertex_id: "fyi.atstore.listing.detail:body.links:items" }
- AddedEdge AddedEdge { src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.label", kind: "prop", name: Some("label") }
- AddedEdge AddedEdge { src: "fyi.atstore.listing.detail:body", tgt: "fyi.atstore.listing.detail:body.links", kind: "prop", name: Some("links") }
- AddedEdge AddedEdge { src: "fyi.atstore.listing.detail:body.links", tgt: "fyi.atstore.listing.detail:body.links:items", kind: "items", name: None }
- AddedEdge AddedEdge { src: "fyi.atstore.listing.detail:body.links:items", tgt: "fyi.atstore.listing.detail#link", kind: "ref", name: None }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "fyi.atstore.listing.detail#link" }AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.label" }AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.type" }AddedVertex { vertex_id: "fyi.atstore.listing.detail#link.url" }AddedVertex { vertex_id: "fyi.atstore.listing.detail:body.links" }AddedVertex { vertex_id: "fyi.atstore.listing.detail:body.links:items" }
Additional Notes
- Breaking: RequiredEdgeAdded { vertex_id: "fyi.atstore.listing.detail#link", src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.url", kind: "prop", name: Some("url") }
- Breaking: RequiredEdgeAdded { vertex_id: "fyi.atstore.listing.detail#link", src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.type", kind: "prop", name: Some("type") }
- Breaking: RequiredEdgeRemoved { vertex_id: "fyi.atstore.listing.detail:body", src: "fyi.atstore.listing.detail:body", tgt: "fyi.atstore.listing.detail:body.heroImage", kind: "prop", name: Some("heroImage") }
- Non-breaking: AddedEdge { src: "fyi.atstore.listing.detail#link", tgt: "fyi.atstore.listing.detail#link.label", kind: "prop", name: Some("label") }
- Non-breaking: AddedEdge { src: "fyi.atstore.listing.detail:body", tgt: "fyi.atstore.listing.detail:body.links", kind: "prop", name: Some("links") }
- Non-breaking: AddedEdge { src: "fyi.atstore.listing.detail:body.links", tgt: "fyi.atstore.listing.detail:body.links:items", kind: "items", name: None }
- Non-breaking: AddedEdge { src: "fyi.atstore.listing.detail:body.links:items", tgt: "fyi.atstore.listing.detail#link", kind: "ref", name: None }
1
1
{
2
2
"id": "fyi.atstore.listing.detail",
3
3
"defs": {
4
+
"link": {
5
+
"type": "object",
6
+
"required": [
7
+
"type",
8
+
"url"
9
+
],
10
+
"properties": {
11
+
"url": {
12
+
"type": "string",
13
+
"format": "uri",
14
+
"maxLength": 2048,
15
+
"description": "The destination URL."
16
+
},
17
+
"type": {
18
+
"type": "string",
19
+
"maxLength": 32,
20
+
"description": "The kind of link.",
21
+
"knownValues": [
22
+
"privacy",
23
+
"terms",
24
+
"support",
25
+
"contact",
26
+
"docs",
27
+
"blog",
28
+
"changelog",
29
+
"source",
30
+
"status",
31
+
"community",
32
+
"donate",
33
+
"license",
34
+
"other"
35
+
]
36
+
},
37
+
"label": {
38
+
"type": "string",
39
+
"maxLength": 100,
40
+
"description": "Optional human-readable label, especially useful when type is 'other'.",
41
+
"maxGraphemes": 50
42
+
}
43
+
}
44
+
},
4
45
"main": {
5
46
"key": "tid",
6
47
"type": "record",
7
48
"record": {
8
49
"type": "object",
9
50
"required": [
10
51
"slug",
11
52
"name",
12
53
"tagline",
13
54
"externalUrl",
14
55
"icon",
15
-
"heroImage",
16
56
"categorySlug",
17
57
"createdAt",
18
58
"updatedAt"
19
59
],
20
60
"properties": {
21
61
"icon": {
22
62
"type": "blob",
23
63
"accept": [
24
64
"image/png",
25
65
"image/jpeg",
26
66
"image/webp",
27
67
"image/gif",
28
68
"image/svg+xml"
29
69
],
30
70
"maxSize": 2000000,
31
71
"description": "Square / app icon (uploaded to repo via com.atproto.repo.uploadBlob)."
32
72
},
33
73
"name": {
34
74
"type": "string",
35
75
"maxLength": 640
36
76
},
37
77
"slug": {
38
78
"type": "string",
39
79
"maxLength": 512,
40
80
"minLength": 1,
41
81
"description": "Stable URL slug; unique within the publishing account."
42
82
},
83
+
"links": {
84
+
"type": "array",
85
+
"items": {
86
+
"ref": "#link",
87
+
"type": "ref"
88
+
},
89
+
"maxLength": 12,
90
+
"description": "Relevant links for the app, including trust/compliance, support, and project resources."
91
+
},
43
92
"appTags": {
44
93
"type": "array",
45
94
"items": {
46
95
"type": "string",
47
96
"maxLength": 96
48
97
},
49
98
"maxLength": 64
50
99
},
51
100
"tagline": {
52
101
"type": "string",
53
102
"maxLength": 300
54
103
},
55
104
"createdAt": {
56
105
"type": "string",
57
106
"format": "datetime"
58
107
},
59
108
"heroImage": {
60
109
"type": "blob",
61
110
"accept": [
62
111
"image/png",
63
112
"image/jpeg",
64
113
"image/webp",
65
114
"image/gif",
66
115
"image/svg+xml"
67
116
],
68
117
"maxSize": 12000000,
69
118
"description": "Hero / cover image blob."
70
119
},
71
120
"updatedAt": {
72
121
"type": "string",
73
122
"format": "datetime"
74
123
},
75
124
"description": {
76
125
"type": "string",
77
126
"maxLength": 20000
78
127
},
79
128
"externalUrl": {
80
129
"type": "string",
81
130
"format": "uri",
82
131
"maxLength": 2048,
83
132
"description": "Primary product or project URL."
84
133
},
85
134
"screenshots": {
86
135
"type": "array",
87
136
"items": {
88
137
"type": "blob",
89
138
"accept": [
90
139
"image/png",
91
140
"image/jpeg",
92
141
"image/webp",
93
142
"image/gif",
94
143
"image/svg+xml"
95
144
],
96
145
"maxSize": 12000000
97
146
},
98
147
"maxLength": 20
99
148
},
100
149
"categorySlug": {
101
150
"type": "array",
102
151
"items": {
103
152
"type": "string",
104
153
"maxLength": 256
105
154
},
106
155
"maxLength": 32,
107
156
"minLength": 1,
108
157
"description": "Browse category keys (e.g. protocol/pds). First entry is the primary category for legacy surfaces."
109
158
},
110
159
"migratedFromAtUri": {
111
160
"type": "string",
112
161
"format": "at-uri",
113
162
"maxLength": 8192,
114
163
"description": "When this listing.detail record supersedes a prior record in another repo (e.g. moved from the AT Store publisher to a product owner PDS), the at:// URI of that prior fyi.atstore.listing.detail record."
115
164
},
116
165
"productAccountDid": {
117
166
"type": "string",
118
167
"maxLength": 2048,
119
168
"description": "Bluesky DID for the product, app, or tool (not the AT Store publisher). Handle is resolved and stored in Postgres only."
120
169
}
121
170
}
122
171
},
123
172
"description": "Public protocol or app listing in the AT Store directory. Images are stored as repo blobs (Kitchen-style); the web app caches HTTPS URLs in Postgres separately."
124
173
}
125
174
},
126
175
"$type": "com.atproto.lexicon.schema",
127
176
"lexicon": 1
128
177
}