net.anisota.chronicle.log.monthly
Schema Diff
+36 -0
Compatibility Analysis
Backward Compatible
Backward compatible. 14 non-breaking changes.
Non-Breaking Changes (14)
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.likes" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.posts" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.quotes" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.replies" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.reposts" }
- AddedVertex AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly:body.inApp" }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.likes", kind: "prop", name: Some("likes") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.posts", kind: "prop", name: Some("posts") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.quotes", kind: "prop", name: Some("quotes") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.replies", kind: "prop", name: Some("replies") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.reposts", kind: "prop", name: Some("reposts") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly:body", tgt: "net.anisota.chronicle.log.monthly:body.inApp", kind: "prop", name: Some("inApp") }
- AddedEdge AddedEdge { src: "net.anisota.chronicle.log.monthly:body.inApp", tgt: "net.anisota.chronicle.log.monthly#inAppCounts", kind: "ref", name: None }
Migration Guidance
Added Elements
AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.likes" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.posts" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.quotes" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.replies" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly#inAppCounts.reposts" }AddedVertex { vertex_id: "net.anisota.chronicle.log.monthly:body.inApp" }
Additional Notes
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.likes", kind: "prop", name: Some("likes") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.posts", kind: "prop", name: Some("posts") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.quotes", kind: "prop", name: Some("quotes") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.replies", kind: "prop", name: Some("replies") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly#inAppCounts", tgt: "net.anisota.chronicle.log.monthly#inAppCounts.reposts", kind: "prop", name: Some("reposts") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly:body", tgt: "net.anisota.chronicle.log.monthly:body.inApp", kind: "prop", name: Some("inApp") }
- Non-breaking: AddedEdge { src: "net.anisota.chronicle.log.monthly:body.inApp", tgt: "net.anisota.chronicle.log.monthly#inAppCounts", kind: "ref", name: None }
1
1
{
2
2
"id": "net.anisota.chronicle.log.monthly",
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
"month",
11
11
"aggregates",
12
12
"status",
13
13
"signature",
14
14
"createdAt"
15
15
],
16
16
"properties": {
17
+
"inApp": {
18
+
"ref": "#inAppCounts",
19
+
"type": "ref",
20
+
"description": "Rolled-up in-anisota activity for the month (summed daily inApp across devices, per field). Optional and additive; the read side may instead compute this from the month's daily logs."
21
+
},
17
22
"month": {
18
23
"type": "string",
19
24
"description": "Month string in YYYY-MM format (e.g. 2026-02)"
20
25
},
21
26
"status": {
22
27
"enum": [
23
28
"active",
24
29
"finalized"
25
30
],
26
31
"type": "string",
27
32
"description": "Whether this month is still being updated or has been finalized"
28
33
},
29
34
"patterns": {
30
35
"ref": "#monthlyPatterns",
31
36
"type": "ref"
32
37
},
33
38
"createdAt": {
34
39
"type": "string",
35
40
"format": "datetime",
36
41
"description": "When the monthly record was first created"
37
42
},
38
43
"signature": {
39
44
"ref": "#chronicleSignature",
40
45
"type": "ref"
41
46
},
42
47
"aggregates": {
43
48
"ref": "#monthlyAggregates",
44
49
"type": "ref"
45
50
},
46
51
"finalizedAt": {
47
52
"type": "string",
48
53
"format": "datetime",
49
54
"description": "When the monthly record was finalized (end of month)"
50
55
},
51
56
"lowerLogRefs": {
52
57
"type": "array",
53
58
"items": {
54
59
"type": "string"
55
60
},
56
61
"description": "AT URIs of weekly log records included in this month"
57
62
},
58
63
"upperLogRefs": {
59
64
"type": "array",
60
65
"items": {
61
66
"type": "string"
62
67
},
63
68
"description": "AT URIs of containing logs (yearly) this month belongs to"
64
69
},
65
70
"expeditionRefs": {
66
71
"type": "array",
67
72
"items": {
68
73
"type": "string"
69
74
},
70
75
"description": "AT URIs of expedition records that occurred during this month"
71
76
}
72
77
}
73
78
},
74
79
"description": "Monthly aggregation of weekly records. rkey is YYYY-MM. Updated once per week, finalized when month ends."
75
80
},
81
+
"inAppCounts": {
82
+
"type": "object",
83
+
"properties": {
84
+
"likes": {
85
+
"type": "integer",
86
+
"minimum": 0,
87
+
"description": "Likes created in anisota"
88
+
},
89
+
"posts": {
90
+
"type": "integer",
91
+
"minimum": 0,
92
+
"description": "Top-level posts created in anisota"
93
+
},
94
+
"quotes": {
95
+
"type": "integer",
96
+
"minimum": 0,
97
+
"description": "Quote posts created in anisota"
98
+
},
99
+
"replies": {
100
+
"type": "integer",
101
+
"minimum": 0,
102
+
"description": "Replies created in anisota"
103
+
},
104
+
"reposts": {
105
+
"type": "integer",
106
+
"minimum": 0,
107
+
"description": "Reposts created in anisota"
108
+
}
109
+
},
110
+
"description": "Per-category counts of activity performed inside anisota, summed across the period and across devices."
111
+
},
76
112
"monthlyPatterns": {
77
113
"type": "object",
78
114
"properties": {
79
115
"peakBlocks": {
80
116
"type": "integer",
81
117
"maximum": 48,
82
118
"minimum": 0,
83
119
"description": "Highest activeBlockCount for any single day in the month"
84
120
},
85
121
"avgBlocksPerDay": {
86
122
"type": "integer",
87
123
"minimum": 0,
88
124
"description": "Average active blocks per day (totalActiveBlocks / daysActive, rounded)"
89
125
},
90
126
"totalActiveBlocks": {
91
127
"type": "integer",
92
128
"minimum": 0,
93
129
"description": "Sum of activeBlockCount across all days in the month"
94
130
}
95
131
},
96
132
"description": "Activity pattern aggregation for the month based on half-hour blocks"
97
133
},
98
134
"monthlyAggregates": {
99
135
"type": "object",
100
136
"properties": {
101
137
"postsRead": {
102
138
"type": "integer",
103
139
"minimum": 0,
104
140
"description": "Total posts read this month"
105
141
},
106
142
"daysActive": {
107
143
"type": "integer",
108
144
"minimum": 0,
109
145
"description": "Number of days with activity this month"
110
146
},
111
147
"weeksActive": {
112
148
"type": "integer",
113
149
"minimum": 0,
114
150
"description": "Number of weeks with activity this month"
115
151
},
116
152
"postsCreated": {
117
153
"type": "integer",
118
154
"minimum": 0,
119
155
"description": "Total posts created this month"
120
156
},
121
157
"likesReceived": {
122
158
"type": "integer",
123
159
"minimum": 0,
124
160
"description": "Total likes received this month"
125
161
},
126
162
"totalXPGained": {
127
163
"type": "integer",
128
164
"minimum": 0,
129
165
"description": "Total XP gained this month"
130
166
},
131
167
"repliesReceived": {
132
168
"type": "integer",
133
169
"minimum": 0,
134
170
"description": "Total replies received this month"
135
171
},
136
172
"specimensPhotographed": {
137
173
"type": "integer",
138
174
"minimum": 0,
139
175
"description": "New specimens photographed this month"
140
176
}
141
177
},
142
178
"description": "Rolled-up counts from weekly records"
143
179
},
144
180
"chronicleSignature": {
145
181
"type": "object",
146
182
"required": [
147
183
"sig",
148
184
"alg",
149
185
"kid",
150
186
"signedAt",
151
187
"nonce",
152
188
"version"
153
189
],
154
190
"properties": {
155
191
"alg": {
156
192
"type": "string",
157
193
"description": "Signing algorithm (ES256)"
158
194
},
159
195
"kid": {
160
196
"type": "string",
161
197
"description": "Key identifier for the signing key"
162
198
},
163
199
"sig": {
164
200
"type": "string",
165
201
"description": "Base64-encoded ES256 signature"
166
202
},
167
203
"nonce": {
168
204
"type": "string",
169
205
"description": "Unique random nonce to prevent replay"
170
206
},
171
207
"version": {
172
208
"type": "integer",
173
209
"description": "Signature schema version"
174
210
},
175
211
"signedAt": {
176
212
"type": "string",
177
213
"format": "datetime",
178
214
"description": "When the record was signed"
179
215
}
180
216
},
181
217
"description": "ES256 cryptographic signature proving record authenticity"
182
218
}
183
219
},
184
220
"$type": "com.atproto.lexicon.schema",
185
221
"lexicon": 1
186
222
}