@atproto/ozone 0.1.140 → 0.1.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/api/moderation/emitEvent.d.ts.map +1 -1
  3. package/dist/api/moderation/emitEvent.js +16 -0
  4. package/dist/api/moderation/emitEvent.js.map +1 -1
  5. package/dist/api/proxied.d.ts.map +1 -1
  6. package/dist/api/proxied.js +9 -0
  7. package/dist/api/proxied.js.map +1 -1
  8. package/dist/api/report/createReport.d.ts.map +1 -1
  9. package/dist/api/report/createReport.js +7 -5
  10. package/dist/api/report/createReport.js.map +1 -1
  11. package/dist/api/util.d.ts +3 -4
  12. package/dist/api/util.d.ts.map +1 -1
  13. package/dist/api/util.js +8 -17
  14. package/dist/api/util.js.map +1 -1
  15. package/dist/config/config.d.ts +1 -0
  16. package/dist/config/config.d.ts.map +1 -1
  17. package/dist/config/config.js +1 -0
  18. package/dist/config/config.js.map +1 -1
  19. package/dist/config/env.d.ts +1 -0
  20. package/dist/config/env.d.ts.map +1 -1
  21. package/dist/config/env.js +1 -0
  22. package/dist/config/env.js.map +1 -1
  23. package/dist/context.d.ts +3 -0
  24. package/dist/context.d.ts.map +1 -1
  25. package/dist/context.js +6 -0
  26. package/dist/context.js.map +1 -1
  27. package/dist/db/migrations/20250718T150931000Z-update-appeal-reason-stats.d.ts +5 -0
  28. package/dist/db/migrations/20250718T150931000Z-update-appeal-reason-stats.d.ts.map +1 -0
  29. package/dist/db/migrations/20250718T150931000Z-update-appeal-reason-stats.js +228 -0
  30. package/dist/db/migrations/20250718T150931000Z-update-appeal-reason-stats.js.map +1 -0
  31. package/dist/db/migrations/index.d.ts +1 -0
  32. package/dist/db/migrations/index.d.ts.map +1 -1
  33. package/dist/db/migrations/index.js +2 -1
  34. package/dist/db/migrations/index.js.map +1 -1
  35. package/dist/db/schema/moderation_event.d.ts +1 -1
  36. package/dist/db/schema/moderation_event.d.ts.map +1 -1
  37. package/dist/lexicon/index.d.ts +49 -0
  38. package/dist/lexicon/index.d.ts.map +1 -1
  39. package/dist/lexicon/index.js +52 -1
  40. package/dist/lexicon/index.js.map +1 -1
  41. package/dist/lexicon/lexicons.d.ts +500 -24
  42. package/dist/lexicon/lexicons.d.ts.map +1 -1
  43. package/dist/lexicon/lexicons.js +344 -7
  44. package/dist/lexicon/lexicons.js.map +1 -1
  45. package/dist/lexicon/types/com/atproto/moderation/defs.d.ts +8 -8
  46. package/dist/lexicon/types/com/atproto/moderation/defs.d.ts.map +1 -1
  47. package/dist/lexicon/types/com/atproto/moderation/defs.js +7 -7
  48. package/dist/lexicon/types/com/atproto/moderation/defs.js.map +1 -1
  49. package/dist/lexicon/types/com/atproto/temp/dereferenceScope.d.ts +24 -0
  50. package/dist/lexicon/types/com/atproto/temp/dereferenceScope.d.ts.map +1 -0
  51. package/dist/lexicon/types/com/atproto/temp/dereferenceScope.js +7 -0
  52. package/dist/lexicon/types/com/atproto/temp/dereferenceScope.js.map +1 -0
  53. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +10 -2
  54. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
  55. package/dist/lexicon/types/tools/ozone/moderation/defs.js +9 -0
  56. package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
  57. package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts +1 -1
  58. package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts.map +1 -1
  59. package/dist/lexicon/types/tools/ozone/moderation/getAccountTimeline.d.ts +1 -1
  60. package/dist/lexicon/types/tools/ozone/moderation/getAccountTimeline.d.ts.map +1 -1
  61. package/dist/lexicon/types/tools/ozone/moderation/getAccountTimeline.js.map +1 -1
  62. package/dist/lexicon/types/tools/ozone/report/defs.d.ts +92 -0
  63. package/dist/lexicon/types/tools/ozone/report/defs.d.ts.map +1 -0
  64. package/dist/lexicon/types/tools/ozone/report/defs.js +98 -0
  65. package/dist/lexicon/types/tools/ozone/report/defs.js.map +1 -0
  66. package/dist/mod-service/index.d.ts +2 -2
  67. package/dist/mod-service/profile.d.ts +15 -0
  68. package/dist/mod-service/profile.d.ts.map +1 -0
  69. package/dist/mod-service/profile.js +135 -0
  70. package/dist/mod-service/profile.js.map +1 -0
  71. package/dist/mod-service/status.d.ts.map +1 -1
  72. package/dist/mod-service/status.js +18 -17
  73. package/dist/mod-service/status.js.map +1 -1
  74. package/dist/tag-service/util.d.ts.map +1 -1
  75. package/dist/tag-service/util.js +7 -1
  76. package/dist/tag-service/util.js.map +1 -1
  77. package/package.json +9 -9
  78. package/src/api/moderation/emitEvent.ts +27 -0
  79. package/src/api/proxied.ts +13 -0
  80. package/src/api/report/createReport.ts +9 -9
  81. package/src/api/util.ts +8 -28
  82. package/src/config/config.ts +3 -1
  83. package/src/config/env.ts +2 -0
  84. package/src/context.ts +14 -0
  85. package/src/db/migrations/20250718T150931000Z-update-appeal-reason-stats.ts +311 -0
  86. package/src/db/migrations/index.ts +1 -0
  87. package/src/db/schema/moderation_event.ts +1 -0
  88. package/src/lexicon/index.ts +82 -0
  89. package/src/lexicon/lexicons.ts +357 -7
  90. package/src/lexicon/types/com/atproto/moderation/defs.ts +52 -7
  91. package/src/lexicon/types/com/atproto/temp/dereferenceScope.ts +42 -0
  92. package/src/lexicon/types/tools/ozone/moderation/defs.ts +23 -0
  93. package/src/lexicon/types/tools/ozone/moderation/emitEvent.ts +1 -0
  94. package/src/lexicon/types/tools/ozone/moderation/getAccountTimeline.ts +1 -0
  95. package/src/lexicon/types/tools/ozone/report/defs.ts +154 -0
  96. package/src/mod-service/profile.ts +143 -0
  97. package/src/mod-service/status.ts +3 -2
  98. package/src/tag-service/util.ts +9 -1
  99. package/tests/__snapshots__/report-reason.test.ts.snap +14 -0
  100. package/tests/report-reason.test.ts +154 -0
  101. package/tests/revoke-account-credentials.test.ts +54 -0
  102. package/tsconfig.build.tsbuildinfo +1 -1
  103. package/tsconfig.tests.tsbuildinfo +1 -1
@@ -1,5 +1,5 @@
1
1
  import assert from 'node:assert'
2
- import { DAY, HOUR } from '@atproto/common'
2
+ import { DAY, HOUR, MINUTE } from '@atproto/common'
3
3
  import { OzoneEnvironment } from './env'
4
4
 
5
5
  // off-config but still from env:
@@ -15,6 +15,7 @@ export const envToCfg = (env: OzoneEnvironment): OzoneConfig => {
15
15
  did: env.serverDid,
16
16
  version: env.version,
17
17
  devMode: env.devMode,
18
+ serviceRecordCacheTTL: env.serviceRecordCacheTTL ?? 5 * MINUTE, // default 5 mins
18
19
  }
19
20
 
20
21
  assert(env.dbPostgresUrl, 'dbPostgresUrl is required')
@@ -124,6 +125,7 @@ export type ServiceConfig = {
124
125
  did: string
125
126
  version?: string
126
127
  devMode?: boolean
128
+ serviceRecordCacheTTL: number // in ms, default 5 mins
127
129
  }
128
130
 
129
131
  export type BlobDivertConfig = {
package/src/config/env.ts CHANGED
@@ -8,6 +8,7 @@ export const readEnv = (): OzoneEnvironment => {
8
8
  port: envInt('OZONE_PORT'),
9
9
  publicUrl: envStr('OZONE_PUBLIC_URL'),
10
10
  serverDid: envStr('OZONE_SERVER_DID'),
11
+ serviceRecordCacheTTL: envInt('OZONE_SERVICE_RECORD_CACHE_TTL'),
11
12
  appviewUrl: envStr('OZONE_APPVIEW_URL'),
12
13
  appviewDid: envStr('OZONE_APPVIEW_DID'),
13
14
  appviewPushEvents: envBool('OZONE_APPVIEW_PUSH_EVENTS'),
@@ -52,6 +53,7 @@ export type OzoneEnvironment = {
52
53
  port?: number
53
54
  publicUrl?: string
54
55
  serverDid?: string
56
+ serviceRecordCacheTTL?: number
55
57
  appviewUrl?: string
56
58
  appviewDid?: string
57
59
  appviewPushEvents?: boolean
package/src/context.ts CHANGED
@@ -17,6 +17,10 @@ import { BlobDiverter } from './daemon/blob-diverter'
17
17
  import { Database } from './db'
18
18
  import { ImageInvalidator } from './image-invalidator'
19
19
  import { ModerationService, ModerationServiceCreator } from './mod-service'
20
+ import {
21
+ ModerationServiceProfile,
22
+ ModerationServiceProfileCreator,
23
+ } from './mod-service/profile'
20
24
  import {
21
25
  SafelinkRuleService,
22
26
  SafelinkRuleServiceCreator,
@@ -45,6 +49,7 @@ export type AppContextOptions = {
45
49
  db: Database
46
50
  cfg: OzoneConfig
47
51
  modService: ModerationServiceCreator
52
+ moderationServiceProfile: ModerationServiceProfileCreator
48
53
  communicationTemplateService: CommunicationTemplateServiceCreator
49
54
  safelinkRuleService: SafelinkRuleServiceCreator
50
55
  setService: SetServiceCreator
@@ -145,6 +150,10 @@ export class AppContext {
145
150
  const settingService = SettingService.creator()
146
151
  const verificationService = VerificationService.creator()
147
152
  const verificationIssuer = VerificationIssuer.creator()
153
+ const moderationServiceProfile = ModerationServiceProfile.creator(
154
+ cfg,
155
+ appviewAgent,
156
+ )
148
157
 
149
158
  const sequencer = new Sequencer(modService(db))
150
159
 
@@ -159,6 +168,7 @@ export class AppContext {
159
168
  db,
160
169
  cfg,
161
170
  modService,
171
+ moderationServiceProfile,
162
172
  communicationTemplateService,
163
173
  safelinkRuleService,
164
174
  teamService,
@@ -235,6 +245,10 @@ export class AppContext {
235
245
  return this.opts.verificationIssuer
236
246
  }
237
247
 
248
+ get moderationServiceProfile(): ModerationServiceProfileCreator {
249
+ return this.opts.moderationServiceProfile
250
+ }
251
+
238
252
  get appviewAgent(): AtpAgent {
239
253
  return this.opts.appviewAgent
240
254
  }
@@ -0,0 +1,311 @@
1
+ import { Kysely, sql } from 'kysely'
2
+ import { OZONE_APPEAL_REASON_TYPE } from '../../api/util'
3
+ import { REASONAPPEAL } from '../../lexicon/types/com/atproto/moderation/defs'
4
+ import { DatabaseSchemaType } from '../schema'
5
+ import * as modEvent from '../schema/moderation_event'
6
+ import * as recordEventsStats from '../schema/record_events_stats'
7
+
8
+ export async function up(db: Kysely<any>): Promise<void> {
9
+ // Drop and recreate materialized views to update appeal reason counting
10
+ // to include both REASONAPPEAL and OZONE_APPEAL_REASON_TYPE
11
+ // The primary difference between the old and new query is that we were using = and != operators
12
+ // to match against the meta->>'reportType' field and now we use IN and NOT IN
13
+
14
+ // Drop existing materialized views in reverse dependency order
15
+ await db.schema
16
+ .dropView('account_record_events_stats')
17
+ .materialized()
18
+ .execute()
19
+ await db.schema.dropView('record_events_stats').materialized().execute()
20
+ await db.schema.dropView('account_events_stats').materialized().execute()
21
+
22
+ // Recreate account_events_stats with updated appeal counting
23
+ await db.schema
24
+ .createView('account_events_stats')
25
+ .materialized()
26
+ .as(
27
+ (db as Kysely<modEvent.PartialDB>)
28
+ .selectFrom('moderation_event')
29
+ .where('subjectType', '=', 'com.atproto.admin.defs#repoRef')
30
+ .where('subjectUri', 'is', null)
31
+ .select('subjectDid')
32
+ .select([
33
+ (eb) =>
34
+ sql<number>`COUNT(*) FILTER(
35
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventTakedown'
36
+ AND ${eb.ref('durationInHours')} IS NULL
37
+ )`.as('takedownCount'),
38
+ (eb) =>
39
+ sql<number>`COUNT(*) FILTER(
40
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventTakedown'
41
+ AND ${eb.ref('durationInHours')} IS NOT NULL
42
+ )`.as('suspendCount'),
43
+ (eb) =>
44
+ sql<number>`COUNT(*) FILTER(
45
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventEscalate'
46
+ )`.as('escalateCount'),
47
+ (eb) =>
48
+ sql<number>`COUNT(*) FILTER(
49
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport'
50
+ AND ${eb.ref('meta')} ->> 'reportType' NOT IN (${REASONAPPEAL}, ${OZONE_APPEAL_REASON_TYPE})
51
+ )`.as('reportCount'),
52
+ (eb) =>
53
+ sql<number>`COUNT(*) FILTER(
54
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport'
55
+ AND ${eb.ref('meta')} ->> 'reportType' IN (${REASONAPPEAL}, ${OZONE_APPEAL_REASON_TYPE})
56
+ )`.as('appealCount'),
57
+ ])
58
+ .groupBy('subjectDid'),
59
+ )
60
+ .execute()
61
+
62
+ // Recreate record_events_stats with updated appeal counting
63
+ await db.schema
64
+ .createView('record_events_stats')
65
+ .materialized()
66
+ .as(
67
+ (db as Kysely<modEvent.PartialDB>)
68
+ .selectFrom('moderation_event')
69
+ .select([
70
+ 'subjectDid',
71
+ 'subjectUri',
72
+ (eb) =>
73
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventEscalate')`.as(
74
+ 'escalateCount',
75
+ ),
76
+ (eb) =>
77
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport' AND ${eb.ref('meta')} ->> 'reportType' NOT IN (${REASONAPPEAL}, ${OZONE_APPEAL_REASON_TYPE}))`.as(
78
+ 'reportCount',
79
+ ),
80
+ (eb) =>
81
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport' AND ${eb.ref('meta')} ->> 'reportType' IN (${REASONAPPEAL}, ${OZONE_APPEAL_REASON_TYPE}))`.as(
82
+ 'appealCount',
83
+ ),
84
+ ])
85
+ .where('subjectType', '=', 'com.atproto.repo.strongRef')
86
+ .where('subjectUri', 'is not', null)
87
+ .groupBy(['subjectDid', 'subjectUri']),
88
+ )
89
+ .execute()
90
+
91
+ // Recreate account_record_events_stats (unchanged logic, but depends on record_events_stats)
92
+ await db.schema
93
+ .createView('account_record_events_stats')
94
+ .materialized()
95
+ .as(
96
+ (db as Kysely<recordEventsStats.PartialDB>)
97
+ .selectFrom('record_events_stats')
98
+ .select([
99
+ 'subjectDid',
100
+ (eb) =>
101
+ sql<number>`SUM(${eb.ref('reportCount')})::bigint`.as(
102
+ 'totalReports',
103
+ ),
104
+ (eb) =>
105
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('reportCount')} > 0)`.as(
106
+ 'reportedCount',
107
+ ),
108
+ (eb) =>
109
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('escalateCount')} > 0)`.as(
110
+ 'escalatedCount',
111
+ ),
112
+ (eb) =>
113
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('appealCount')} > 0)`.as(
114
+ 'appealedCount',
115
+ ),
116
+ ])
117
+ .groupBy('subjectDid'),
118
+ )
119
+ .execute()
120
+
121
+ // Recreate all indexes for the materialized views
122
+ await db.schema
123
+ .createIndex('account_events_stats_did_idx')
124
+ .unique()
125
+ .on('account_events_stats')
126
+ .column('subjectDid')
127
+ .execute()
128
+
129
+ await db.schema
130
+ .createIndex('account_events_stats_suspend_count_idx')
131
+ .on('account_events_stats')
132
+ .expression(sql`"suspendCount" ASC NULLS FIRST`)
133
+ .column('subjectDid')
134
+ .execute()
135
+
136
+ await db.schema
137
+ .createIndex('record_events_stats_uri_idx')
138
+ .unique()
139
+ .on('record_events_stats')
140
+ .column('subjectUri')
141
+ .execute()
142
+
143
+ await db.schema
144
+ .createIndex('record_events_stats_did_idx')
145
+ .on('record_events_stats')
146
+ .column('subjectDid')
147
+ .execute()
148
+
149
+ await db.schema
150
+ .createIndex('account_record_events_stats_did_idx')
151
+ .unique()
152
+ .on('account_record_events_stats')
153
+ .column('subjectDid')
154
+ .execute()
155
+
156
+ await db.schema
157
+ .createIndex('account_record_events_stats_reported_count_idx')
158
+ .on('account_record_events_stats')
159
+ .expression(sql`"reportedCount" ASC NULLS FIRST`)
160
+ .column('subjectDid')
161
+ .execute()
162
+ }
163
+
164
+ export async function down(db: Kysely<DatabaseSchemaType>): Promise<void> {
165
+ // Drop the updated materialized views
166
+ await db.schema
167
+ .dropView('account_record_events_stats')
168
+ .materialized()
169
+ .execute()
170
+ await db.schema.dropView('record_events_stats').materialized().execute()
171
+ await db.schema.dropView('account_events_stats').materialized().execute()
172
+
173
+ // Recreate the original views with single appeal reason type
174
+ await db.schema
175
+ .createView('account_events_stats')
176
+ .materialized()
177
+ .as(
178
+ (db as Kysely<modEvent.PartialDB>)
179
+ .selectFrom('moderation_event')
180
+ .where('subjectType', '=', 'com.atproto.admin.defs#repoRef')
181
+ .where('subjectUri', 'is', null)
182
+ .select('subjectDid')
183
+ .select([
184
+ (eb) =>
185
+ sql<number>`COUNT(*) FILTER(
186
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventTakedown'
187
+ AND ${eb.ref('durationInHours')} IS NULL
188
+ )`.as('takedownCount'),
189
+ (eb) =>
190
+ sql<number>`COUNT(*) FILTER(
191
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventTakedown'
192
+ AND ${eb.ref('durationInHours')} IS NOT NULL
193
+ )`.as('suspendCount'),
194
+ (eb) =>
195
+ sql<number>`COUNT(*) FILTER(
196
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventEscalate'
197
+ )`.as('escalateCount'),
198
+ (eb) =>
199
+ sql<number>`COUNT(*) FILTER(
200
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport'
201
+ AND ${eb.ref('meta')} ->> 'reportType' != ${REASONAPPEAL}
202
+ )`.as('reportCount'),
203
+ (eb) =>
204
+ sql<number>`COUNT(*) FILTER(
205
+ WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport'
206
+ AND ${eb.ref('meta')} ->> 'reportType' = ${REASONAPPEAL}
207
+ )`.as('appealCount'),
208
+ ])
209
+ .groupBy('subjectDid'),
210
+ )
211
+ .execute()
212
+
213
+ await db.schema
214
+ .createView('record_events_stats')
215
+ .materialized()
216
+ .as(
217
+ (db as Kysely<modEvent.PartialDB>)
218
+ .selectFrom('moderation_event')
219
+ .select([
220
+ 'subjectDid',
221
+ 'subjectUri',
222
+ (eb) =>
223
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventEscalate')`.as(
224
+ 'escalateCount',
225
+ ),
226
+ (eb) =>
227
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport' AND ${eb.ref('meta')} ->> 'reportType' != 'com.atproto.moderation.defs#reasonAppeal')`.as(
228
+ 'reportCount',
229
+ ),
230
+ (eb) =>
231
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('action')} = 'tools.ozone.moderation.defs#modEventReport' AND ${eb.ref('meta')} ->> 'reportType' = 'com.atproto.moderation.defs#reasonAppeal')`.as(
232
+ 'appealCount',
233
+ ),
234
+ ])
235
+ .where('subjectType', '=', 'com.atproto.repo.strongRef')
236
+ .where('subjectUri', 'is not', null)
237
+ .groupBy(['subjectDid', 'subjectUri']),
238
+ )
239
+ .execute()
240
+
241
+ await db.schema
242
+ .createView('account_record_events_stats')
243
+ .materialized()
244
+ .as(
245
+ (db as Kysely<recordEventsStats.PartialDB>)
246
+ .selectFrom('record_events_stats')
247
+ .select([
248
+ 'subjectDid',
249
+ (eb) =>
250
+ sql<number>`SUM(${eb.ref('reportCount')})::bigint`.as(
251
+ 'totalReports',
252
+ ),
253
+ (eb) =>
254
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('reportCount')} > 0)`.as(
255
+ 'reportedCount',
256
+ ),
257
+ (eb) =>
258
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('escalateCount')} > 0)`.as(
259
+ 'escalatedCount',
260
+ ),
261
+ (eb) =>
262
+ sql<number>`COUNT(*) FILTER (WHERE ${eb.ref('appealCount')} > 0)`.as(
263
+ 'appealedCount',
264
+ ),
265
+ ])
266
+ .groupBy('subjectDid'),
267
+ )
268
+ .execute()
269
+
270
+ // Recreate indexes
271
+ await db.schema
272
+ .createIndex('account_events_stats_did_idx')
273
+ .unique()
274
+ .on('account_events_stats')
275
+ .column('subjectDid')
276
+ .execute()
277
+
278
+ await db.schema
279
+ .createIndex('account_events_stats_suspend_count_idx')
280
+ .on('account_events_stats')
281
+ .expression(sql`"suspendCount" ASC NULLS FIRST`)
282
+ .column('subjectDid')
283
+ .execute()
284
+
285
+ await db.schema
286
+ .createIndex('record_events_stats_uri_idx')
287
+ .unique()
288
+ .on('record_events_stats')
289
+ .column('subjectUri')
290
+ .execute()
291
+
292
+ await db.schema
293
+ .createIndex('record_events_stats_did_idx')
294
+ .on('record_events_stats')
295
+ .column('subjectDid')
296
+ .execute()
297
+
298
+ await db.schema
299
+ .createIndex('account_record_events_stats_did_idx')
300
+ .unique()
301
+ .on('account_record_events_stats')
302
+ .column('subjectDid')
303
+ .execute()
304
+
305
+ await db.schema
306
+ .createIndex('account_record_events_stats_reported_count_idx')
307
+ .on('account_record_events_stats')
308
+ .expression(sql`"reportedCount" ASC NULLS FIRST`)
309
+ .column('subjectDid')
310
+ .execute()
311
+ }
@@ -29,3 +29,4 @@ export * as _20250609T110704000Z from './20250609T110704000Z-safelink'
29
29
  export * as _20250618T180246000Z from './20250618T180246000Z-add-mod-tool-to-moderation-event'
30
30
  export * as _20250701T000000000Z from './20250701T000000000Z-add-age-assurance-state'
31
31
  export * as _20250715T000000000Z from './20250715T000000000Z-add-mod-event-external-id'
32
+ export * as _20250718T150931000Z from './20250718T150931000Z-update-appeal-reason-stats'
@@ -25,6 +25,7 @@ export interface ModerationEvent {
25
25
  | 'tools.ozone.moderation.defs#modEventPriorityScore'
26
26
  | 'tools.ozone.moderation.defs#ageAssuranceEvent'
27
27
  | 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent'
28
+ | 'tools.ozone.moderation.defs#revokeAccountCredentialsEvent'
28
29
  subjectType:
29
30
  | 'com.atproto.admin.defs#repoRef'
30
31
  | 'com.atproto.repo.strongRef'
@@ -198,6 +198,7 @@ import * as ComAtprotoSyncSubscribeRepos from './types/com/atproto/sync/subscrib
198
198
  import * as ComAtprotoTempAddReservedHandle from './types/com/atproto/temp/addReservedHandle.js'
199
199
  import * as ComAtprotoTempCheckHandleAvailability from './types/com/atproto/temp/checkHandleAvailability.js'
200
200
  import * as ComAtprotoTempCheckSignupQueue from './types/com/atproto/temp/checkSignupQueue.js'
201
+ import * as ComAtprotoTempDereferenceScope from './types/com/atproto/temp/dereferenceScope.js'
201
202
  import * as ComAtprotoTempFetchLabels from './types/com/atproto/temp/fetchLabels.js'
202
203
  import * as ComAtprotoTempRequestPhoneVerification from './types/com/atproto/temp/requestPhoneVerification.js'
203
204
  import * as ComAtprotoTempRevokeAccountCredentials from './types/com/atproto/temp/revokeAccountCredentials.js'
@@ -289,6 +290,75 @@ export const TOOLS_OZONE_MODERATION = {
289
290
  DefsTimelineEventPlcTombstone:
290
291
  'tools.ozone.moderation.defs#timelineEventPlcTombstone',
291
292
  }
293
+ export const TOOLS_OZONE_REPORT = {
294
+ DefsReasonAppeal: 'tools.ozone.report.defs#reasonAppeal',
295
+ DefsReasonViolenceAnimalWelfare:
296
+ 'tools.ozone.report.defs#reasonViolenceAnimalWelfare',
297
+ DefsReasonViolenceThreats: 'tools.ozone.report.defs#reasonViolenceThreats',
298
+ DefsReasonViolenceGraphicContent:
299
+ 'tools.ozone.report.defs#reasonViolenceGraphicContent',
300
+ DefsReasonViolenceSelfHarm: 'tools.ozone.report.defs#reasonViolenceSelfHarm',
301
+ DefsReasonViolenceGlorification:
302
+ 'tools.ozone.report.defs#reasonViolenceGlorification',
303
+ DefsReasonViolenceExtremistContent:
304
+ 'tools.ozone.report.defs#reasonViolenceExtremistContent',
305
+ DefsReasonViolenceTrafficking:
306
+ 'tools.ozone.report.defs#reasonViolenceTrafficking',
307
+ DefsReasonViolenceOther: 'tools.ozone.report.defs#reasonViolenceOther',
308
+ DefsReasonSexualAbuseContent:
309
+ 'tools.ozone.report.defs#reasonSexualAbuseContent',
310
+ DefsReasonSexualNCII: 'tools.ozone.report.defs#reasonSexualNCII',
311
+ DefsReasonSexualSextortion: 'tools.ozone.report.defs#reasonSexualSextortion',
312
+ DefsReasonSexualDeepfake: 'tools.ozone.report.defs#reasonSexualDeepfake',
313
+ DefsReasonSexualAnimal: 'tools.ozone.report.defs#reasonSexualAnimal',
314
+ DefsReasonSexualUnlabeled: 'tools.ozone.report.defs#reasonSexualUnlabeled',
315
+ DefsReasonSexualOther: 'tools.ozone.report.defs#reasonSexualOther',
316
+ DefsReasonChildSafetyCSAM: 'tools.ozone.report.defs#reasonChildSafetyCSAM',
317
+ DefsReasonChildSafetyGroom: 'tools.ozone.report.defs#reasonChildSafetyGroom',
318
+ DefsReasonChildSafetyMinorPrivacy:
319
+ 'tools.ozone.report.defs#reasonChildSafetyMinorPrivacy',
320
+ DefsReasonChildSafetyEndangerment:
321
+ 'tools.ozone.report.defs#reasonChildSafetyEndangerment',
322
+ DefsReasonChildSafetyHarassment:
323
+ 'tools.ozone.report.defs#reasonChildSafetyHarassment',
324
+ DefsReasonChildSafetyPromotion:
325
+ 'tools.ozone.report.defs#reasonChildSafetyPromotion',
326
+ DefsReasonChildSafetyOther: 'tools.ozone.report.defs#reasonChildSafetyOther',
327
+ DefsReasonHarassmentTroll: 'tools.ozone.report.defs#reasonHarassmentTroll',
328
+ DefsReasonHarassmentTargeted:
329
+ 'tools.ozone.report.defs#reasonHarassmentTargeted',
330
+ DefsReasonHarassmentHateSpeech:
331
+ 'tools.ozone.report.defs#reasonHarassmentHateSpeech',
332
+ DefsReasonHarassmentDoxxing:
333
+ 'tools.ozone.report.defs#reasonHarassmentDoxxing',
334
+ DefsReasonHarassmentOther: 'tools.ozone.report.defs#reasonHarassmentOther',
335
+ DefsReasonMisleadingBot: 'tools.ozone.report.defs#reasonMisleadingBot',
336
+ DefsReasonMisleadingImpersonation:
337
+ 'tools.ozone.report.defs#reasonMisleadingImpersonation',
338
+ DefsReasonMisleadingSpam: 'tools.ozone.report.defs#reasonMisleadingSpam',
339
+ DefsReasonMisleadingScam: 'tools.ozone.report.defs#reasonMisleadingScam',
340
+ DefsReasonMisleadingSyntheticContent:
341
+ 'tools.ozone.report.defs#reasonMisleadingSyntheticContent',
342
+ DefsReasonMisleadingMisinformation:
343
+ 'tools.ozone.report.defs#reasonMisleadingMisinformation',
344
+ DefsReasonMisleadingOther: 'tools.ozone.report.defs#reasonMisleadingOther',
345
+ DefsReasonRuleSiteSecurity: 'tools.ozone.report.defs#reasonRuleSiteSecurity',
346
+ DefsReasonRuleStolenContent:
347
+ 'tools.ozone.report.defs#reasonRuleStolenContent',
348
+ DefsReasonRuleProhibitedSales:
349
+ 'tools.ozone.report.defs#reasonRuleProhibitedSales',
350
+ DefsReasonRuleBanEvasion: 'tools.ozone.report.defs#reasonRuleBanEvasion',
351
+ DefsReasonRuleOther: 'tools.ozone.report.defs#reasonRuleOther',
352
+ DefsReasonCivicElectoralProcess:
353
+ 'tools.ozone.report.defs#reasonCivicElectoralProcess',
354
+ DefsReasonCivicDisclosure: 'tools.ozone.report.defs#reasonCivicDisclosure',
355
+ DefsReasonCivicInterference:
356
+ 'tools.ozone.report.defs#reasonCivicInterference',
357
+ DefsReasonCivicMisinformation:
358
+ 'tools.ozone.report.defs#reasonCivicMisinformation',
359
+ DefsReasonCivicImpersonation:
360
+ 'tools.ozone.report.defs#reasonCivicImpersonation',
361
+ }
292
362
  export const TOOLS_OZONE_TEAM = {
293
363
  DefsRoleAdmin: 'tools.ozone.team.defs#roleAdmin',
294
364
  DefsRoleModerator: 'tools.ozone.team.defs#roleModerator',
@@ -2843,6 +2913,18 @@ export class ComAtprotoTempNS {
2843
2913
  return this._server.xrpc.method(nsid, cfg)
2844
2914
  }
2845
2915
 
2916
+ dereferenceScope<A extends Auth = void>(
2917
+ cfg: MethodConfigOrHandler<
2918
+ A,
2919
+ ComAtprotoTempDereferenceScope.QueryParams,
2920
+ ComAtprotoTempDereferenceScope.HandlerInput,
2921
+ ComAtprotoTempDereferenceScope.HandlerOutput
2922
+ >,
2923
+ ) {
2924
+ const nsid = 'com.atproto.temp.dereferenceScope' // @ts-ignore
2925
+ return this._server.xrpc.method(nsid, cfg)
2926
+ }
2927
+
2846
2928
  fetchLabels<A extends Auth = void>(
2847
2929
  cfg: MethodConfigOrHandler<
2848
2930
  A,