@atproto/ozone 0.1.165 → 0.1.167
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.
- package/CHANGELOG.md +20 -0
- package/dist/api/moderation/emitEvent.d.ts.map +1 -1
- package/dist/api/moderation/emitEvent.js +8 -0
- package/dist/api/moderation/emitEvent.js.map +1 -1
- package/dist/api/util.d.ts +1 -1
- package/dist/api/util.d.ts.map +1 -1
- package/dist/api/util.js +1 -0
- package/dist/api/util.js.map +1 -1
- package/dist/db/schema/moderation_event.d.ts +1 -1
- package/dist/db/schema/moderation_event.d.ts.map +1 -1
- package/dist/db/schema/moderation_event.js.map +1 -1
- package/dist/lexicon/lexicons.d.ts +70 -6
- package/dist/lexicon/lexicons.d.ts.map +1 -1
- package/dist/lexicon/lexicons.js +35 -0
- package/dist/lexicon/lexicons.js.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/getSuggestions.d.ts +3 -1
- package/dist/lexicon/types/app/bsky/actor/getSuggestions.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/actor/getSuggestions.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getOnboardingSuggestedUsersSkeleton.d.ts +3 -1
- package/dist/lexicon/types/app/bsky/unspecced/getOnboardingSuggestedUsersSkeleton.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getOnboardingSuggestedUsersSkeleton.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts +3 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.d.ts +3 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsers.js.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.d.ts +3 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.d.ts.map +1 -1
- package/dist/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +10 -2
- package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/defs.js +9 -0
- package/dist/lexicon/types/tools/ozone/moderation/defs.js.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.d.ts.map +1 -1
- package/dist/lexicon/types/tools/ozone/moderation/emitEvent.js.map +1 -1
- package/dist/mod-service/index.d.ts +3 -2
- package/dist/mod-service/index.d.ts.map +1 -1
- package/dist/mod-service/index.js +11 -0
- package/dist/mod-service/index.js.map +1 -1
- package/dist/mod-service/status.d.ts.map +1 -1
- package/dist/mod-service/status.js +7 -0
- package/dist/mod-service/status.js.map +1 -1
- package/package.json +5 -5
- package/src/api/moderation/emitEvent.ts +17 -1
- package/src/api/util.ts +1 -0
- package/src/db/schema/moderation_event.ts +1 -0
- package/src/lexicon/lexicons.ts +36 -0
- package/src/lexicon/types/app/bsky/actor/getSuggestions.ts +3 -1
- package/src/lexicon/types/app/bsky/unspecced/getOnboardingSuggestedUsersSkeleton.ts +3 -1
- package/src/lexicon/types/app/bsky/unspecced/getSuggestedOnboardingUsers.ts +3 -1
- package/src/lexicon/types/app/bsky/unspecced/getSuggestedUsers.ts +3 -1
- package/src/lexicon/types/app/bsky/unspecced/getSuggestedUsersSkeleton.ts +3 -1
- package/src/lexicon/types/tools/ozone/moderation/defs.ts +19 -0
- package/src/lexicon/types/tools/ozone/moderation/emitEvent.ts +1 -0
- package/src/mod-service/index.ts +14 -0
- package/src/mod-service/status.ts +8 -0
- package/tests/__snapshots__/get-starter-pack.test.ts.snap +9 -9
- package/tests/__snapshots__/get-subjects.test.ts.snap +2 -2
- package/tests/__snapshots__/team.test.ts.snap +4 -4
- package/tests/__snapshots__/verification-listener.test.ts.snap +2 -2
- package/tests/__snapshots__/verification.test.ts.snap +3 -3
- package/tests/_util.ts +6 -4
- package/tests/age-assurance.test.ts +134 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/mod-service/status.ts"],"names":[],"mappings":"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","sourcesContent":["// This may require better organization but for now, just dumping functions here containing DB queries for moderation status\n\nimport { HOUR } from '@atproto/common'\nimport { AtUri } from '@atproto/syntax'\nimport { isAppealReport } from '../api/util'\nimport { Database } from '../db'\nimport { DatabaseSchema } from '../db/schema'\nimport { jsonb } from '../db/types'\nimport {\n REVIEWCLOSED,\n REVIEWESCALATED,\n REVIEWNONE,\n REVIEWOPEN,\n} from '../lexicon/types/tools/ozone/moderation/defs'\nimport { ModerationEventRow, ModerationSubjectStatusRow } from './types'\n\nconst getSubjectStatusForModerationEvent = ({\n currentStatus,\n action,\n createdBy,\n createdAt,\n durationInHours,\n}: {\n currentStatus?: ModerationSubjectStatusRow\n action: string\n createdBy: string\n createdAt: string\n durationInHours: number | null\n}): Partial<ModerationSubjectStatusRow> => {\n const defaultReviewState = currentStatus\n ? currentStatus.reviewState\n : REVIEWNONE\n\n switch (action) {\n case 'tools.ozone.moderation.defs#modEventAcknowledge':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventReport':\n return {\n reviewState: REVIEWOPEN,\n lastReportedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventEscalate':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWESCALATED,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventReverseTakedown':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n takendown: false,\n suspendUntil: null,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventUnmuteReporter':\n return {\n lastReviewedBy: createdBy,\n muteReportingUntil: null,\n // It's not likely to receive an unmute event that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventUnmute':\n return {\n lastReviewedBy: createdBy,\n muteUntil: null,\n // It's not likely to receive an unmute event that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventTakedown':\n return {\n // If we are doing a takedown, safe to move the item out of appealed state\n ...(currentStatus?.appealed ? { appealed: false } : {}),\n takendown: true,\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n lastReviewedAt: createdAt,\n suspendUntil: durationInHours\n ? new Date(Date.now() + durationInHours * HOUR).toISOString()\n : null,\n }\n case 'tools.ozone.moderation.defs#modEventMuteReporter':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n // By default, mute for 24hrs\n muteReportingUntil: new Date(\n Date.now() + (durationInHours || 24) * HOUR,\n ).toISOString(),\n // It's not likely to receive a mute event on a subject that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventMute':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n // By default, mute for 24hrs\n muteUntil: new Date(\n Date.now() + (durationInHours || 24) * HOUR,\n ).toISOString(),\n // It's not likely to receive a mute event on a subject that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventComment':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventTag':\n return { tags: [], reviewState: defaultReviewState }\n case 'tools.ozone.moderation.defs#modEventResolveAppeal':\n return {\n appealed: false,\n }\n case 'tools.ozone.moderation.defs#ageAssuranceEvent':\n case 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent':\n return {\n reviewState: defaultReviewState,\n }\n default:\n return {}\n }\n}\n\nconst hostingEvents = [\n 'tools.ozone.moderation.defs#accountEvent',\n 'tools.ozone.moderation.defs#identityEvent',\n 'tools.ozone.moderation.defs#recordEvent',\n]\n\nconst getSubjectStatusForRecordEvent = ({\n event,\n currentStatus,\n}: {\n event: ModerationEventRow\n currentStatus?: ModerationSubjectStatusRow\n}): Partial<ModerationSubjectStatusRow> => {\n const timestamp =\n typeof event.meta?.timestamp === 'string'\n ? event.meta?.timestamp\n : event.createdAt\n\n if (event.action === 'tools.ozone.moderation.defs#recordEvent') {\n if (event.meta?.op === 'delete') {\n return {\n hostingStatus: 'deleted',\n hostingDeletedAt: timestamp,\n }\n } else if (event.meta?.op === 'update') {\n return {\n hostingStatus: 'active',\n hostingUpdatedAt: timestamp,\n }\n }\n return {}\n }\n\n if (event.action === 'tools.ozone.moderation.defs#accountEvent') {\n const status: Partial<ModerationSubjectStatusRow> = {\n hostingUpdatedAt: timestamp,\n }\n\n if (event.meta?.status) {\n status.hostingStatus = `${event.meta?.status}`\n }\n\n if (event.meta?.status === 'deleted') {\n status.hostingDeletedAt = timestamp\n } else if (event.meta?.status === 'deactivated') {\n status.hostingDeactivatedAt = timestamp\n } else {\n // When deactivated accounts are re-activated, we receive the event with just the active flag set to true\n // so we want to make sure that the hostingStatus is not set to an outdated value\n if (\n currentStatus?.hostingStatus === 'deactivated' &&\n event.meta?.active\n ) {\n status.hostingStatus = 'active'\n status.hostingReactivatedAt = timestamp\n }\n }\n\n return status\n }\n\n if (event.action === 'tools.ozone.moderation.defs#identityEvent') {\n const status: Partial<ModerationSubjectStatusRow> = {\n hostingUpdatedAt: timestamp,\n }\n\n if (event.meta?.tombstone) {\n status.hostingStatus = 'tombstoned'\n status.hostingDeletedAt = timestamp\n }\n\n return status\n }\n\n return {}\n}\n\nexport const moderationSubjectStatusQueryBuilder = (db: DatabaseSchema) => {\n // @NOTE: Using select() instead of selectAll() below because the materialized\n // views might be incomplete, and we don't want the null `did` columns to\n // interfere with the (never null) `did` column from the\n // `moderation_subject_status` table in the results\n return db\n .selectFrom('moderation_subject_status')\n .selectAll('moderation_subject_status')\n .leftJoin('account_events_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_events_stats.subjectDid',\n ),\n )\n .select([\n 'account_events_stats.takedownCount',\n 'account_events_stats.suspendCount',\n 'account_events_stats.escalateCount',\n 'account_events_stats.reportCount',\n 'account_events_stats.appealCount',\n ])\n .leftJoin('account_record_events_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_record_events_stats.subjectDid',\n ),\n )\n .select([\n 'account_record_events_stats.totalReports',\n 'account_record_events_stats.reportedCount',\n 'account_record_events_stats.escalatedCount',\n 'account_record_events_stats.appealedCount',\n ])\n .leftJoin('account_record_status_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_record_status_stats.did',\n ),\n )\n .select([\n 'account_record_status_stats.subjectCount',\n 'account_record_status_stats.pendingCount',\n 'account_record_status_stats.processedCount',\n 'account_record_status_stats.takendownCount',\n ])\n .leftJoin('account_strike', (join) =>\n join.onRef('moderation_subject_status.did', '=', 'account_strike.did'),\n )\n .select([\n 'account_strike.activeStrikeCount as strikeCount',\n 'account_strike.totalStrikeCount',\n 'account_strike.firstStrikeAt',\n 'account_strike.lastStrikeAt',\n ])\n}\n\n// Based on a given moderation action event, this function will update the moderation status of the subject\n// If there's no existing status, it will create one\n// If the action event does not affect the status, it will do nothing\nexport const adjustModerationSubjectStatus = async (\n db: Database,\n moderationEvent: ModerationEventRow,\n blobCids?: string[],\n): Promise<ModerationSubjectStatusRow | null> => {\n const {\n action,\n subjectDid,\n subjectUri,\n subjectCid,\n createdBy,\n meta,\n addedTags,\n removedTags,\n comment,\n createdAt,\n } = moderationEvent\n\n // If subjectUri exists, it's not a repoRef so pass along the uri to get identifier back\n const identifier = getStatusIdentifierFromSubject(subjectUri || subjectDid)\n\n db.assertTransaction()\n\n const now = new Date().toISOString()\n const currentStatus = await db.db\n .selectFrom('moderation_subject_status')\n .where('did', '=', identifier.did)\n .where('recordPath', '=', identifier.recordPath)\n // Make sure we respect other updates that may be happening at the same time\n .forUpdate()\n .selectAll()\n .executeTakeFirst()\n\n if (hostingEvents.includes(action)) {\n const newStatus = getSubjectStatusForRecordEvent({\n event: moderationEvent,\n currentStatus,\n })\n if (!Object.keys(newStatus).length) {\n return currentStatus || null\n }\n\n const status = await db.db\n .insertInto('moderation_subject_status')\n .values({\n ...identifier,\n ...newStatus,\n // newStatus doesn't contain a reviewState or takendown so in case this is a new entry\n // we need to set a default values so that the insert doesn't fail\n reviewState: currentStatus ? currentStatus.reviewState : REVIEWNONE,\n // @TODO: should we try to update this based on status property of account event?\n // For now we're the only one emitting takedowns so i don't think it makes too much of a difference\n takendown: currentStatus ? currentStatus.takendown : false,\n ageAssuranceState: currentStatus\n ? currentStatus.ageAssuranceState\n : 'unknown',\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.constraint('moderation_status_unique_idx').doUpdateSet({\n ...newStatus,\n updatedAt: now,\n }),\n )\n .returningAll()\n .executeTakeFirst()\n\n return status || null\n }\n\n // If reporting is muted for this reporter, we don't want to update the subject status\n if (meta?.isReporterMuted) {\n return currentStatus || null\n }\n\n const isAppealEvent =\n action === 'tools.ozone.moderation.defs#modEventReport' &&\n meta?.reportType &&\n isAppealReport(`${meta.reportType}`)\n\n const subjectStatus = getSubjectStatusForModerationEvent({\n currentStatus,\n action,\n createdBy,\n createdAt,\n durationInHours: moderationEvent.durationInHours,\n })\n\n if (\n currentStatus?.reviewState === REVIEWESCALATED &&\n subjectStatus.reviewState !== REVIEWCLOSED\n ) {\n // If the current status is escalated only allow incoming events to move the state to\n // reviewClosed because escalated subjects should never move to any other state\n subjectStatus.reviewState = REVIEWESCALATED\n }\n\n if (currentStatus && subjectStatus.reviewState === REVIEWNONE) {\n // reviewNone is ONLY allowed when there is no current status\n // If there is a current status, it should not be allowed to move back to reviewNone\n subjectStatus.reviewState = currentStatus.reviewState\n }\n\n // Set these because we don't want to override them if they're already set\n const defaultData = {\n comment: null,\n // Defaulting reviewState to open for any event may not be the desired behavior.\n // For instance, if a subject never had any event and we just want to leave a comment to keep an eye on it\n // that shouldn't mean we want to review the subject\n reviewState: REVIEWNONE,\n recordCid: subjectCid || null,\n ageAssuranceState: currentStatus?.ageAssuranceState || 'unknown',\n }\n const newStatus = {\n ...defaultData,\n ...subjectStatus,\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventPriorityScore' &&\n typeof meta?.priorityScore === 'number'\n ) {\n newStatus.priorityScore = meta?.priorityScore\n subjectStatus.priorityScore = meta?.priorityScore\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventReverseTakedown' &&\n !subjectStatus.takendown\n ) {\n newStatus.takendown = false\n subjectStatus.takendown = false\n }\n\n if (isAppealEvent) {\n newStatus.appealed = true\n subjectStatus.appealed = true\n newStatus.lastAppealedAt = createdAt\n subjectStatus.lastAppealedAt = createdAt\n // Set reviewState to escalated when appeal events are emitted\n subjectStatus.reviewState = REVIEWESCALATED\n newStatus.reviewState = REVIEWESCALATED\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventResolveAppeal' &&\n subjectStatus.appealed\n ) {\n newStatus.appealed = false\n subjectStatus.appealed = false\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventComment' &&\n meta?.sticky\n ) {\n newStatus.comment = comment\n subjectStatus.comment = comment\n }\n\n if (action === 'tools.ozone.moderation.defs#modEventTag') {\n let tags = currentStatus?.tags || []\n if (addedTags?.length) {\n tags = tags.concat(addedTags)\n }\n if (removedTags?.length) {\n tags = tags.filter((tag) => !removedTags.includes(tag))\n }\n newStatus.tags = jsonb([...new Set(tags)]) as unknown as string[]\n subjectStatus.tags = newStatus.tags\n }\n\n if (action === 'tools.ozone.moderation.defs#ageAssuranceEvent') {\n // Only when the last update was made by an admin AND state was set to reset user event can override final state\n if (\n currentStatus?.ageAssuranceUpdatedBy !== 'admin' ||\n currentStatus?.ageAssuranceState === 'reset'\n ) {\n if (typeof meta?.status === 'string') {\n newStatus.ageAssuranceState = meta.status\n subjectStatus.ageAssuranceState = meta.status\n newStatus.ageAssuranceUpdatedBy = 'user'\n subjectStatus.ageAssuranceUpdatedBy = 'user'\n }\n }\n }\n\n if (action === 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent') {\n if (typeof meta?.status === 'string') {\n newStatus.ageAssuranceState = meta.status\n subjectStatus.ageAssuranceState = meta.status\n newStatus.ageAssuranceUpdatedBy = 'admin'\n subjectStatus.ageAssuranceUpdatedBy = 'admin'\n }\n }\n\n if (blobCids?.length) {\n const newBlobCids = jsonb(\n blobCids,\n ) as unknown as ModerationSubjectStatusRow['blobCids']\n newStatus.blobCids = newBlobCids\n subjectStatus.blobCids = newBlobCids\n }\n\n const insertQuery = db.db\n .insertInto('moderation_subject_status')\n .values({\n ...identifier,\n ...newStatus,\n createdAt: now,\n updatedAt: now,\n } as ModerationSubjectStatusRow)\n .onConflict((oc) =>\n oc.constraint('moderation_status_unique_idx').doUpdateSet({\n ...subjectStatus,\n updatedAt: now,\n }),\n )\n\n const status = await insertQuery.returningAll().executeTakeFirst()\n return status || null\n}\n\nexport const getStatusIdentifierFromSubject = (\n subject: string | AtUri,\n): { did: string; recordPath: string } => {\n const isSubjectString = typeof subject === 'string'\n if (isSubjectString && subject.startsWith('did:')) {\n return {\n did: subject,\n recordPath: '',\n }\n }\n\n if (isSubjectString && !subject.startsWith('at://')) {\n throw new Error('Subject is neither a did nor an at-uri')\n }\n\n const uri = isSubjectString ? new AtUri(subject) : subject\n return {\n did: uri.host,\n recordPath: `${uri.collection}/${uri.rkey}`,\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/mod-service/status.ts"],"names":[],"mappings":"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","sourcesContent":["// This may require better organization but for now, just dumping functions here containing DB queries for moderation status\n\nimport { HOUR } from '@atproto/common'\nimport { AtUri } from '@atproto/syntax'\nimport { isAppealReport } from '../api/util'\nimport { Database } from '../db'\nimport { DatabaseSchema } from '../db/schema'\nimport { jsonb } from '../db/types'\nimport {\n REVIEWCLOSED,\n REVIEWESCALATED,\n REVIEWNONE,\n REVIEWOPEN,\n} from '../lexicon/types/tools/ozone/moderation/defs'\nimport { ModerationEventRow, ModerationSubjectStatusRow } from './types'\n\nconst getSubjectStatusForModerationEvent = ({\n currentStatus,\n action,\n createdBy,\n createdAt,\n durationInHours,\n}: {\n currentStatus?: ModerationSubjectStatusRow\n action: string\n createdBy: string\n createdAt: string\n durationInHours: number | null\n}): Partial<ModerationSubjectStatusRow> => {\n const defaultReviewState = currentStatus\n ? currentStatus.reviewState\n : REVIEWNONE\n\n switch (action) {\n case 'tools.ozone.moderation.defs#modEventAcknowledge':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventReport':\n return {\n reviewState: REVIEWOPEN,\n lastReportedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventEscalate':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWESCALATED,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventReverseTakedown':\n return {\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n takendown: false,\n suspendUntil: null,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventUnmuteReporter':\n return {\n lastReviewedBy: createdBy,\n muteReportingUntil: null,\n // It's not likely to receive an unmute event that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventUnmute':\n return {\n lastReviewedBy: createdBy,\n muteUntil: null,\n // It's not likely to receive an unmute event that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n lastReviewedAt: createdAt,\n }\n case 'tools.ozone.moderation.defs#modEventTakedown':\n return {\n // If we are doing a takedown, safe to move the item out of appealed state\n ...(currentStatus?.appealed ? { appealed: false } : {}),\n takendown: true,\n lastReviewedBy: createdBy,\n reviewState: REVIEWCLOSED,\n lastReviewedAt: createdAt,\n suspendUntil: durationInHours\n ? new Date(Date.now() + durationInHours * HOUR).toISOString()\n : null,\n }\n case 'tools.ozone.moderation.defs#modEventMuteReporter':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n // By default, mute for 24hrs\n muteReportingUntil: new Date(\n Date.now() + (durationInHours || 24) * HOUR,\n ).toISOString(),\n // It's not likely to receive a mute event on a subject that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventMute':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n // By default, mute for 24hrs\n muteUntil: new Date(\n Date.now() + (durationInHours || 24) * HOUR,\n ).toISOString(),\n // It's not likely to receive a mute event on a subject that does not already have a status row\n // but if it does happen, default to unnecessary\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventComment':\n return {\n lastReviewedBy: createdBy,\n lastReviewedAt: createdAt,\n reviewState: defaultReviewState,\n }\n case 'tools.ozone.moderation.defs#modEventTag':\n return { tags: [], reviewState: defaultReviewState }\n case 'tools.ozone.moderation.defs#modEventResolveAppeal':\n return {\n appealed: false,\n }\n case 'tools.ozone.moderation.defs#ageAssuranceEvent':\n case 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent':\n case 'tools.ozone.moderation.defs#ageAssurancePurgeEvent':\n return {\n reviewState: defaultReviewState,\n }\n default:\n return {}\n }\n}\n\nconst hostingEvents = [\n 'tools.ozone.moderation.defs#accountEvent',\n 'tools.ozone.moderation.defs#identityEvent',\n 'tools.ozone.moderation.defs#recordEvent',\n]\n\nconst getSubjectStatusForRecordEvent = ({\n event,\n currentStatus,\n}: {\n event: ModerationEventRow\n currentStatus?: ModerationSubjectStatusRow\n}): Partial<ModerationSubjectStatusRow> => {\n const timestamp =\n typeof event.meta?.timestamp === 'string'\n ? event.meta?.timestamp\n : event.createdAt\n\n if (event.action === 'tools.ozone.moderation.defs#recordEvent') {\n if (event.meta?.op === 'delete') {\n return {\n hostingStatus: 'deleted',\n hostingDeletedAt: timestamp,\n }\n } else if (event.meta?.op === 'update') {\n return {\n hostingStatus: 'active',\n hostingUpdatedAt: timestamp,\n }\n }\n return {}\n }\n\n if (event.action === 'tools.ozone.moderation.defs#accountEvent') {\n const status: Partial<ModerationSubjectStatusRow> = {\n hostingUpdatedAt: timestamp,\n }\n\n if (event.meta?.status) {\n status.hostingStatus = `${event.meta?.status}`\n }\n\n if (event.meta?.status === 'deleted') {\n status.hostingDeletedAt = timestamp\n } else if (event.meta?.status === 'deactivated') {\n status.hostingDeactivatedAt = timestamp\n } else {\n // When deactivated accounts are re-activated, we receive the event with just the active flag set to true\n // so we want to make sure that the hostingStatus is not set to an outdated value\n if (\n currentStatus?.hostingStatus === 'deactivated' &&\n event.meta?.active\n ) {\n status.hostingStatus = 'active'\n status.hostingReactivatedAt = timestamp\n }\n }\n\n return status\n }\n\n if (event.action === 'tools.ozone.moderation.defs#identityEvent') {\n const status: Partial<ModerationSubjectStatusRow> = {\n hostingUpdatedAt: timestamp,\n }\n\n if (event.meta?.tombstone) {\n status.hostingStatus = 'tombstoned'\n status.hostingDeletedAt = timestamp\n }\n\n return status\n }\n\n return {}\n}\n\nexport const moderationSubjectStatusQueryBuilder = (db: DatabaseSchema) => {\n // @NOTE: Using select() instead of selectAll() below because the materialized\n // views might be incomplete, and we don't want the null `did` columns to\n // interfere with the (never null) `did` column from the\n // `moderation_subject_status` table in the results\n return db\n .selectFrom('moderation_subject_status')\n .selectAll('moderation_subject_status')\n .leftJoin('account_events_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_events_stats.subjectDid',\n ),\n )\n .select([\n 'account_events_stats.takedownCount',\n 'account_events_stats.suspendCount',\n 'account_events_stats.escalateCount',\n 'account_events_stats.reportCount',\n 'account_events_stats.appealCount',\n ])\n .leftJoin('account_record_events_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_record_events_stats.subjectDid',\n ),\n )\n .select([\n 'account_record_events_stats.totalReports',\n 'account_record_events_stats.reportedCount',\n 'account_record_events_stats.escalatedCount',\n 'account_record_events_stats.appealedCount',\n ])\n .leftJoin('account_record_status_stats', (join) =>\n join.onRef(\n 'moderation_subject_status.did',\n '=',\n 'account_record_status_stats.did',\n ),\n )\n .select([\n 'account_record_status_stats.subjectCount',\n 'account_record_status_stats.pendingCount',\n 'account_record_status_stats.processedCount',\n 'account_record_status_stats.takendownCount',\n ])\n .leftJoin('account_strike', (join) =>\n join.onRef('moderation_subject_status.did', '=', 'account_strike.did'),\n )\n .select([\n 'account_strike.activeStrikeCount as strikeCount',\n 'account_strike.totalStrikeCount',\n 'account_strike.firstStrikeAt',\n 'account_strike.lastStrikeAt',\n ])\n}\n\n// Based on a given moderation action event, this function will update the moderation status of the subject\n// If there's no existing status, it will create one\n// If the action event does not affect the status, it will do nothing\nexport const adjustModerationSubjectStatus = async (\n db: Database,\n moderationEvent: ModerationEventRow,\n blobCids?: string[],\n): Promise<ModerationSubjectStatusRow | null> => {\n const {\n action,\n subjectDid,\n subjectUri,\n subjectCid,\n createdBy,\n meta,\n addedTags,\n removedTags,\n comment,\n createdAt,\n } = moderationEvent\n\n // If subjectUri exists, it's not a repoRef so pass along the uri to get identifier back\n const identifier = getStatusIdentifierFromSubject(subjectUri || subjectDid)\n\n db.assertTransaction()\n\n const now = new Date().toISOString()\n const currentStatus = await db.db\n .selectFrom('moderation_subject_status')\n .where('did', '=', identifier.did)\n .where('recordPath', '=', identifier.recordPath)\n // Make sure we respect other updates that may be happening at the same time\n .forUpdate()\n .selectAll()\n .executeTakeFirst()\n\n if (hostingEvents.includes(action)) {\n const newStatus = getSubjectStatusForRecordEvent({\n event: moderationEvent,\n currentStatus,\n })\n if (!Object.keys(newStatus).length) {\n return currentStatus || null\n }\n\n const status = await db.db\n .insertInto('moderation_subject_status')\n .values({\n ...identifier,\n ...newStatus,\n // newStatus doesn't contain a reviewState or takendown so in case this is a new entry\n // we need to set a default values so that the insert doesn't fail\n reviewState: currentStatus ? currentStatus.reviewState : REVIEWNONE,\n // @TODO: should we try to update this based on status property of account event?\n // For now we're the only one emitting takedowns so i don't think it makes too much of a difference\n takendown: currentStatus ? currentStatus.takendown : false,\n ageAssuranceState: currentStatus\n ? currentStatus.ageAssuranceState\n : 'unknown',\n createdAt: now,\n updatedAt: now,\n })\n .onConflict((oc) =>\n oc.constraint('moderation_status_unique_idx').doUpdateSet({\n ...newStatus,\n updatedAt: now,\n }),\n )\n .returningAll()\n .executeTakeFirst()\n\n return status || null\n }\n\n // If reporting is muted for this reporter, we don't want to update the subject status\n if (meta?.isReporterMuted) {\n return currentStatus || null\n }\n\n const isAppealEvent =\n action === 'tools.ozone.moderation.defs#modEventReport' &&\n meta?.reportType &&\n isAppealReport(`${meta.reportType}`)\n\n const subjectStatus = getSubjectStatusForModerationEvent({\n currentStatus,\n action,\n createdBy,\n createdAt,\n durationInHours: moderationEvent.durationInHours,\n })\n\n if (\n currentStatus?.reviewState === REVIEWESCALATED &&\n subjectStatus.reviewState !== REVIEWCLOSED\n ) {\n // If the current status is escalated only allow incoming events to move the state to\n // reviewClosed because escalated subjects should never move to any other state\n subjectStatus.reviewState = REVIEWESCALATED\n }\n\n if (currentStatus && subjectStatus.reviewState === REVIEWNONE) {\n // reviewNone is ONLY allowed when there is no current status\n // If there is a current status, it should not be allowed to move back to reviewNone\n subjectStatus.reviewState = currentStatus.reviewState\n }\n\n // Set these because we don't want to override them if they're already set\n const defaultData = {\n comment: null,\n // Defaulting reviewState to open for any event may not be the desired behavior.\n // For instance, if a subject never had any event and we just want to leave a comment to keep an eye on it\n // that shouldn't mean we want to review the subject\n reviewState: REVIEWNONE,\n recordCid: subjectCid || null,\n ageAssuranceState: currentStatus?.ageAssuranceState || 'unknown',\n }\n const newStatus = {\n ...defaultData,\n ...subjectStatus,\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventPriorityScore' &&\n typeof meta?.priorityScore === 'number'\n ) {\n newStatus.priorityScore = meta?.priorityScore\n subjectStatus.priorityScore = meta?.priorityScore\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventReverseTakedown' &&\n !subjectStatus.takendown\n ) {\n newStatus.takendown = false\n subjectStatus.takendown = false\n }\n\n if (isAppealEvent) {\n newStatus.appealed = true\n subjectStatus.appealed = true\n newStatus.lastAppealedAt = createdAt\n subjectStatus.lastAppealedAt = createdAt\n // Set reviewState to escalated when appeal events are emitted\n subjectStatus.reviewState = REVIEWESCALATED\n newStatus.reviewState = REVIEWESCALATED\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventResolveAppeal' &&\n subjectStatus.appealed\n ) {\n newStatus.appealed = false\n subjectStatus.appealed = false\n }\n\n if (\n action === 'tools.ozone.moderation.defs#modEventComment' &&\n meta?.sticky\n ) {\n newStatus.comment = comment\n subjectStatus.comment = comment\n }\n\n if (action === 'tools.ozone.moderation.defs#modEventTag') {\n let tags = currentStatus?.tags || []\n if (addedTags?.length) {\n tags = tags.concat(addedTags)\n }\n if (removedTags?.length) {\n tags = tags.filter((tag) => !removedTags.includes(tag))\n }\n newStatus.tags = jsonb([...new Set(tags)]) as unknown as string[]\n subjectStatus.tags = newStatus.tags\n }\n\n if (action === 'tools.ozone.moderation.defs#ageAssuranceEvent') {\n // Only when the last update was made by an admin AND state was set to reset user event can override final state\n if (\n currentStatus?.ageAssuranceUpdatedBy !== 'admin' ||\n currentStatus?.ageAssuranceState === 'reset'\n ) {\n if (typeof meta?.status === 'string') {\n newStatus.ageAssuranceState = meta.status\n subjectStatus.ageAssuranceState = meta.status\n newStatus.ageAssuranceUpdatedBy = 'user'\n subjectStatus.ageAssuranceUpdatedBy = 'user'\n }\n }\n }\n\n if (action === 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent') {\n if (typeof meta?.status === 'string') {\n newStatus.ageAssuranceState = meta.status\n subjectStatus.ageAssuranceState = meta.status\n newStatus.ageAssuranceUpdatedBy = 'admin'\n subjectStatus.ageAssuranceUpdatedBy = 'admin'\n }\n }\n\n if (action === 'tools.ozone.moderation.defs#ageAssurancePurgeEvent') {\n newStatus.ageAssuranceState = 'unknown'\n subjectStatus.ageAssuranceState = 'unknown'\n newStatus.ageAssuranceUpdatedBy = null\n subjectStatus.ageAssuranceUpdatedBy = null\n }\n\n if (blobCids?.length) {\n const newBlobCids = jsonb(\n blobCids,\n ) as unknown as ModerationSubjectStatusRow['blobCids']\n newStatus.blobCids = newBlobCids\n subjectStatus.blobCids = newBlobCids\n }\n\n const insertQuery = db.db\n .insertInto('moderation_subject_status')\n .values({\n ...identifier,\n ...newStatus,\n createdAt: now,\n updatedAt: now,\n } as ModerationSubjectStatusRow)\n .onConflict((oc) =>\n oc.constraint('moderation_status_unique_idx').doUpdateSet({\n ...subjectStatus,\n updatedAt: now,\n }),\n )\n\n const status = await insertQuery.returningAll().executeTakeFirst()\n return status || null\n}\n\nexport const getStatusIdentifierFromSubject = (\n subject: string | AtUri,\n): { did: string; recordPath: string } => {\n const isSubjectString = typeof subject === 'string'\n if (isSubjectString && subject.startsWith('did:')) {\n return {\n did: subject,\n recordPath: '',\n }\n }\n\n if (isSubjectString && !subject.startsWith('at://')) {\n throw new Error('Subject is neither a did nor an at-uri')\n }\n\n const uri = isSubjectString ? new AtUri(subject) : subject\n return {\n did: uri.host,\n recordPath: `${uri.collection}/${uri.rkey}`,\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atproto/ozone",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.167",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Backend service for moderating the Bluesky network.",
|
|
6
6
|
"keywords": [
|
|
@@ -35,15 +35,15 @@
|
|
|
35
35
|
"uint8arrays": "3.0.0",
|
|
36
36
|
"undici": "^6.14.1",
|
|
37
37
|
"ws": "^8.12.0",
|
|
38
|
-
"@atproto/api": "^0.19.
|
|
38
|
+
"@atproto/api": "^0.19.4",
|
|
39
39
|
"@atproto/common": "^0.5.14",
|
|
40
40
|
"@atproto/crypto": "^0.4.5",
|
|
41
41
|
"@atproto/identity": "^0.4.12",
|
|
42
42
|
"@atproto/lexicon": "^0.6.2",
|
|
43
|
-
"@atproto/syntax": "^0.5.
|
|
43
|
+
"@atproto/syntax": "^0.5.1",
|
|
44
44
|
"@atproto/ws-client": "^0.0.4",
|
|
45
45
|
"@atproto/xrpc": "^0.7.7",
|
|
46
|
-
"@atproto/xrpc-server": "^0.10.
|
|
46
|
+
"@atproto/xrpc-server": "^0.10.16"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@did-plc/server": "^0.0.1",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"ts-node": "^10.8.2",
|
|
57
57
|
"typescript": "^5.6.3",
|
|
58
58
|
"@atproto/lex-cli": "^0.9.9",
|
|
59
|
-
"@atproto/pds": "^0.4.
|
|
59
|
+
"@atproto/pds": "^0.4.215"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
62
|
"codegen": "lex gen-server --yes ./src/lexicon ../../lexicons/com/atproto/*/* ../../lexicons/app/bsky/*/* ../../lexicons/chat/bsky/*/* ../../lexicons/tools/ozone/*/*",
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { isModEventDivert } from '@atproto/api/dist/client/types/tools/ozone/moderation/defs'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
AuthRequiredError,
|
|
4
|
+
ForbiddenError,
|
|
5
|
+
InvalidRequestError,
|
|
6
|
+
} from '@atproto/xrpc-server'
|
|
3
7
|
import { AdminTokenOutput, ModeratorOutput } from '../../auth-verifier'
|
|
4
8
|
import { AppContext } from '../../context'
|
|
5
9
|
import { Server } from '../../lexicon'
|
|
@@ -8,6 +12,7 @@ import {
|
|
|
8
12
|
ModEventTag,
|
|
9
13
|
isAgeAssuranceEvent,
|
|
10
14
|
isAgeAssuranceOverrideEvent,
|
|
15
|
+
isAgeAssurancePurgeEvent,
|
|
11
16
|
isModEventAcknowledge,
|
|
12
17
|
isModEventEmail,
|
|
13
18
|
isModEventLabel,
|
|
@@ -71,6 +76,17 @@ const handleModerationEvent = async ({
|
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
|
|
79
|
+
if (isAgeAssurancePurgeEvent(event)) {
|
|
80
|
+
if (!subject.isRepo()) {
|
|
81
|
+
throw new InvalidRequestError('Invalid subject type')
|
|
82
|
+
}
|
|
83
|
+
if (!auth.credentials.isModerator) {
|
|
84
|
+
throw new ForbiddenError(
|
|
85
|
+
'Must be a moderator to purge age assurance events',
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
74
90
|
if (isRevokeAccountCredentialsEvent(event)) {
|
|
75
91
|
if (!subject.isRepo()) {
|
|
76
92
|
throw new InvalidRequestError('Invalid subject type')
|
package/src/api/util.ts
CHANGED
|
@@ -157,6 +157,7 @@ const eventTypes = new Set([
|
|
|
157
157
|
'tools.ozone.moderation.defs#modEventPriorityScore',
|
|
158
158
|
'tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
159
159
|
'tools.ozone.moderation.defs#ageAssuranceOverrideEvent',
|
|
160
|
+
'tools.ozone.moderation.defs#ageAssurancePurgeEvent',
|
|
160
161
|
'tools.ozone.moderation.defs#revokeAccountCredentialsEvent',
|
|
161
162
|
'tools.ozone.moderation.defs#scheduleTakedownEvent',
|
|
162
163
|
'tools.ozone.moderation.defs#cancelScheduledTakedownEvent',
|
|
@@ -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#ageAssurancePurgeEvent'
|
|
28
29
|
| 'tools.ozone.moderation.defs#revokeAccountCredentialsEvent'
|
|
29
30
|
subjectType:
|
|
30
31
|
| 'com.atproto.admin.defs#repoRef'
|
package/src/lexicon/lexicons.ts
CHANGED
|
@@ -1028,6 +1028,10 @@ export const schemaDict = {
|
|
|
1028
1028
|
},
|
|
1029
1029
|
recId: {
|
|
1030
1030
|
type: 'integer',
|
|
1031
|
+
description: 'DEPRECATED: use recIdStr instead.',
|
|
1032
|
+
},
|
|
1033
|
+
recIdStr: {
|
|
1034
|
+
type: 'string',
|
|
1031
1035
|
description:
|
|
1032
1036
|
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
1033
1037
|
},
|
|
@@ -8107,6 +8111,10 @@ export const schemaDict = {
|
|
|
8107
8111
|
},
|
|
8108
8112
|
},
|
|
8109
8113
|
recId: {
|
|
8114
|
+
type: 'string',
|
|
8115
|
+
description: 'DEPRECATED: use recIdStr instead.',
|
|
8116
|
+
},
|
|
8117
|
+
recIdStr: {
|
|
8110
8118
|
type: 'string',
|
|
8111
8119
|
description:
|
|
8112
8120
|
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
@@ -8441,6 +8449,10 @@ export const schemaDict = {
|
|
|
8441
8449
|
},
|
|
8442
8450
|
},
|
|
8443
8451
|
recId: {
|
|
8452
|
+
type: 'string',
|
|
8453
|
+
description: 'DEPRECATED: use recIdStr instead.',
|
|
8454
|
+
},
|
|
8455
|
+
recIdStr: {
|
|
8444
8456
|
type: 'string',
|
|
8445
8457
|
description:
|
|
8446
8458
|
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
@@ -8568,6 +8580,10 @@ export const schemaDict = {
|
|
|
8568
8580
|
},
|
|
8569
8581
|
},
|
|
8570
8582
|
recId: {
|
|
8583
|
+
type: 'string',
|
|
8584
|
+
description: 'DEPRECATED: use recIdStr instead.',
|
|
8585
|
+
},
|
|
8586
|
+
recIdStr: {
|
|
8571
8587
|
type: 'string',
|
|
8572
8588
|
description:
|
|
8573
8589
|
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
@@ -8621,6 +8637,10 @@ export const schemaDict = {
|
|
|
8621
8637
|
},
|
|
8622
8638
|
},
|
|
8623
8639
|
recId: {
|
|
8640
|
+
type: 'string',
|
|
8641
|
+
description: 'DEPRECATED: use recIdStr instead.',
|
|
8642
|
+
},
|
|
8643
|
+
recIdStr: {
|
|
8624
8644
|
type: 'string',
|
|
8625
8645
|
description:
|
|
8626
8646
|
'Snowflake for this recommendation, use when submitting recommendation events.',
|
|
@@ -15929,6 +15949,7 @@ export const schemaDict = {
|
|
|
15929
15949
|
'lex:tools.ozone.moderation.defs#modEventPriorityScore',
|
|
15930
15950
|
'lex:tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
15931
15951
|
'lex:tools.ozone.moderation.defs#ageAssuranceOverrideEvent',
|
|
15952
|
+
'lex:tools.ozone.moderation.defs#ageAssurancePurgeEvent',
|
|
15932
15953
|
'lex:tools.ozone.moderation.defs#revokeAccountCredentialsEvent',
|
|
15933
15954
|
'lex:tools.ozone.moderation.defs#scheduleTakedownEvent',
|
|
15934
15955
|
'lex:tools.ozone.moderation.defs#cancelScheduledTakedownEvent',
|
|
@@ -16006,6 +16027,7 @@ export const schemaDict = {
|
|
|
16006
16027
|
'lex:tools.ozone.moderation.defs#modEventPriorityScore',
|
|
16007
16028
|
'lex:tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
16008
16029
|
'lex:tools.ozone.moderation.defs#ageAssuranceOverrideEvent',
|
|
16030
|
+
'lex:tools.ozone.moderation.defs#ageAssurancePurgeEvent',
|
|
16009
16031
|
'lex:tools.ozone.moderation.defs#revokeAccountCredentialsEvent',
|
|
16010
16032
|
'lex:tools.ozone.moderation.defs#scheduleTakedownEvent',
|
|
16011
16033
|
'lex:tools.ozone.moderation.defs#cancelScheduledTakedownEvent',
|
|
@@ -16572,6 +16594,19 @@ export const schemaDict = {
|
|
|
16572
16594
|
},
|
|
16573
16595
|
},
|
|
16574
16596
|
},
|
|
16597
|
+
ageAssurancePurgeEvent: {
|
|
16598
|
+
type: 'object',
|
|
16599
|
+
description:
|
|
16600
|
+
'Purges all age assurance events for the subject. Only works on DID subjects. Moderator-only.',
|
|
16601
|
+
required: ['comment'],
|
|
16602
|
+
properties: {
|
|
16603
|
+
comment: {
|
|
16604
|
+
type: 'string',
|
|
16605
|
+
minLength: 1,
|
|
16606
|
+
description: 'Comment describing the reason for the purge.',
|
|
16607
|
+
},
|
|
16608
|
+
},
|
|
16609
|
+
},
|
|
16575
16610
|
revokeAccountCredentialsEvent: {
|
|
16576
16611
|
type: 'object',
|
|
16577
16612
|
description:
|
|
@@ -17445,6 +17480,7 @@ export const schemaDict = {
|
|
|
17445
17480
|
'lex:tools.ozone.moderation.defs#modEventPriorityScore',
|
|
17446
17481
|
'lex:tools.ozone.moderation.defs#ageAssuranceEvent',
|
|
17447
17482
|
'lex:tools.ozone.moderation.defs#ageAssuranceOverrideEvent',
|
|
17483
|
+
'lex:tools.ozone.moderation.defs#ageAssurancePurgeEvent',
|
|
17448
17484
|
'lex:tools.ozone.moderation.defs#revokeAccountCredentialsEvent',
|
|
17449
17485
|
'lex:tools.ozone.moderation.defs#scheduleTakedownEvent',
|
|
17450
17486
|
'lex:tools.ozone.moderation.defs#cancelScheduledTakedownEvent',
|
|
@@ -24,8 +24,10 @@ export type InputSchema = undefined
|
|
|
24
24
|
export interface OutputSchema {
|
|
25
25
|
cursor?: string
|
|
26
26
|
actors: AppBskyActorDefs.ProfileView[]
|
|
27
|
-
/**
|
|
27
|
+
/** DEPRECATED: use recIdStr instead. */
|
|
28
28
|
recId?: number
|
|
29
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
30
|
+
recIdStr?: string
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export type HandlerInput = void
|
|
@@ -25,8 +25,10 @@ export type InputSchema = undefined
|
|
|
25
25
|
|
|
26
26
|
export interface OutputSchema {
|
|
27
27
|
dids: string[]
|
|
28
|
-
/**
|
|
28
|
+
/** DEPRECATED: use recIdStr instead. */
|
|
29
29
|
recId?: string
|
|
30
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
31
|
+
recIdStr?: string
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export type HandlerInput = void
|
|
@@ -24,8 +24,10 @@ export type InputSchema = undefined
|
|
|
24
24
|
|
|
25
25
|
export interface OutputSchema {
|
|
26
26
|
actors: AppBskyActorDefs.ProfileView[]
|
|
27
|
-
/**
|
|
27
|
+
/** DEPRECATED: use recIdStr instead. */
|
|
28
28
|
recId?: string
|
|
29
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
30
|
+
recIdStr?: string
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export type HandlerInput = void
|
|
@@ -24,8 +24,10 @@ export type InputSchema = undefined
|
|
|
24
24
|
|
|
25
25
|
export interface OutputSchema {
|
|
26
26
|
actors: AppBskyActorDefs.ProfileView[]
|
|
27
|
-
/**
|
|
27
|
+
/** DEPRECATED: use recIdStr instead. */
|
|
28
28
|
recId?: string
|
|
29
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
30
|
+
recIdStr?: string
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export type HandlerInput = void
|
|
@@ -25,8 +25,10 @@ export type InputSchema = undefined
|
|
|
25
25
|
|
|
26
26
|
export interface OutputSchema {
|
|
27
27
|
dids: string[]
|
|
28
|
-
/**
|
|
28
|
+
/** DEPRECATED: use recIdStr instead. */
|
|
29
29
|
recId?: string
|
|
30
|
+
/** Snowflake for this recommendation, use when submitting recommendation events. */
|
|
31
|
+
recIdStr?: string
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
export type HandlerInput = void
|
|
@@ -46,6 +46,7 @@ export interface ModEventView {
|
|
|
46
46
|
| $Typed<ModEventPriorityScore>
|
|
47
47
|
| $Typed<AgeAssuranceEvent>
|
|
48
48
|
| $Typed<AgeAssuranceOverrideEvent>
|
|
49
|
+
| $Typed<AgeAssurancePurgeEvent>
|
|
49
50
|
| $Typed<RevokeAccountCredentialsEvent>
|
|
50
51
|
| $Typed<ScheduleTakedownEvent>
|
|
51
52
|
| $Typed<CancelScheduledTakedownEvent>
|
|
@@ -98,6 +99,7 @@ export interface ModEventViewDetail {
|
|
|
98
99
|
| $Typed<ModEventPriorityScore>
|
|
99
100
|
| $Typed<AgeAssuranceEvent>
|
|
100
101
|
| $Typed<AgeAssuranceOverrideEvent>
|
|
102
|
+
| $Typed<AgeAssurancePurgeEvent>
|
|
101
103
|
| $Typed<RevokeAccountCredentialsEvent>
|
|
102
104
|
| $Typed<ScheduleTakedownEvent>
|
|
103
105
|
| $Typed<CancelScheduledTakedownEvent>
|
|
@@ -503,6 +505,23 @@ export function validateAgeAssuranceOverrideEvent<V>(v: V) {
|
|
|
503
505
|
)
|
|
504
506
|
}
|
|
505
507
|
|
|
508
|
+
/** Purges all age assurance events for the subject. Only works on DID subjects. Moderator-only. */
|
|
509
|
+
export interface AgeAssurancePurgeEvent {
|
|
510
|
+
$type?: 'tools.ozone.moderation.defs#ageAssurancePurgeEvent'
|
|
511
|
+
/** Comment describing the reason for the purge. */
|
|
512
|
+
comment: string
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
const hashAgeAssurancePurgeEvent = 'ageAssurancePurgeEvent'
|
|
516
|
+
|
|
517
|
+
export function isAgeAssurancePurgeEvent<V>(v: V) {
|
|
518
|
+
return is$typed(v, id, hashAgeAssurancePurgeEvent)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export function validateAgeAssurancePurgeEvent<V>(v: V) {
|
|
522
|
+
return validate<AgeAssurancePurgeEvent & V>(v, id, hashAgeAssurancePurgeEvent)
|
|
523
|
+
}
|
|
524
|
+
|
|
506
525
|
/** Account credentials revocation by moderators. Only works on DID subjects. */
|
|
507
526
|
export interface RevokeAccountCredentialsEvent {
|
|
508
527
|
$type?: 'tools.ozone.moderation.defs#revokeAccountCredentialsEvent'
|
|
@@ -42,6 +42,7 @@ export interface InputSchema {
|
|
|
42
42
|
| $Typed<ToolsOzoneModerationDefs.ModEventPriorityScore>
|
|
43
43
|
| $Typed<ToolsOzoneModerationDefs.AgeAssuranceEvent>
|
|
44
44
|
| $Typed<ToolsOzoneModerationDefs.AgeAssuranceOverrideEvent>
|
|
45
|
+
| $Typed<ToolsOzoneModerationDefs.AgeAssurancePurgeEvent>
|
|
45
46
|
| $Typed<ToolsOzoneModerationDefs.RevokeAccountCredentialsEvent>
|
|
46
47
|
| $Typed<ToolsOzoneModerationDefs.ScheduleTakedownEvent>
|
|
47
48
|
| $Typed<ToolsOzoneModerationDefs.CancelScheduledTakedownEvent>
|
package/src/mod-service/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
isAccountEvent,
|
|
29
29
|
isAgeAssuranceEvent,
|
|
30
30
|
isAgeAssuranceOverrideEvent,
|
|
31
|
+
isAgeAssurancePurgeEvent,
|
|
31
32
|
isIdentityEvent,
|
|
32
33
|
isModEventAcknowledge,
|
|
33
34
|
isModEventComment,
|
|
@@ -665,6 +666,10 @@ export class ModerationService {
|
|
|
665
666
|
subject.blobCids,
|
|
666
667
|
)
|
|
667
668
|
|
|
669
|
+
if (isAgeAssurancePurgeEvent(event)) {
|
|
670
|
+
await this.purgeAgeAssuranceEvents(subjectInfo.subjectDid)
|
|
671
|
+
}
|
|
672
|
+
|
|
668
673
|
// Updates are only needed if strikeCount is numeric (in some cases even 0)
|
|
669
674
|
if (modEvent.strikeCount !== null) {
|
|
670
675
|
try {
|
|
@@ -681,6 +686,15 @@ export class ModerationService {
|
|
|
681
686
|
return { event: modEvent, subjectStatus }
|
|
682
687
|
}
|
|
683
688
|
|
|
689
|
+
async purgeAgeAssuranceEvents(subjectDid: string) {
|
|
690
|
+
this.db.assertTransaction()
|
|
691
|
+
await this.db.db
|
|
692
|
+
.deleteFrom('moderation_event')
|
|
693
|
+
.where('subjectDid', '=', subjectDid)
|
|
694
|
+
.where('action', '=', 'tools.ozone.moderation.defs#ageAssuranceEvent')
|
|
695
|
+
.execute()
|
|
696
|
+
}
|
|
697
|
+
|
|
684
698
|
async getLastReversibleEventForSubject(subject: ReversalSubject) {
|
|
685
699
|
// If the subject is neither suspended nor muted don't bother finding the last reversible event
|
|
686
700
|
// Ideally, this should never happen because the caller of this method should only call this
|
|
@@ -125,6 +125,7 @@ const getSubjectStatusForModerationEvent = ({
|
|
|
125
125
|
}
|
|
126
126
|
case 'tools.ozone.moderation.defs#ageAssuranceEvent':
|
|
127
127
|
case 'tools.ozone.moderation.defs#ageAssuranceOverrideEvent':
|
|
128
|
+
case 'tools.ozone.moderation.defs#ageAssurancePurgeEvent':
|
|
128
129
|
return {
|
|
129
130
|
reviewState: defaultReviewState,
|
|
130
131
|
}
|
|
@@ -469,6 +470,13 @@ export const adjustModerationSubjectStatus = async (
|
|
|
469
470
|
}
|
|
470
471
|
}
|
|
471
472
|
|
|
473
|
+
if (action === 'tools.ozone.moderation.defs#ageAssurancePurgeEvent') {
|
|
474
|
+
newStatus.ageAssuranceState = 'unknown'
|
|
475
|
+
subjectStatus.ageAssuranceState = 'unknown'
|
|
476
|
+
newStatus.ageAssuranceUpdatedBy = null
|
|
477
|
+
subjectStatus.ageAssuranceUpdatedBy = null
|
|
478
|
+
}
|
|
479
|
+
|
|
472
480
|
if (blobCids?.length) {
|
|
473
481
|
const newBlobCids = jsonb(
|
|
474
482
|
blobCids,
|
|
@@ -10,7 +10,7 @@ Object {
|
|
|
10
10
|
"allowSubscriptions": "followers",
|
|
11
11
|
},
|
|
12
12
|
},
|
|
13
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
13
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
14
14
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
15
15
|
"did": "user(0)",
|
|
16
16
|
"displayName": "ali",
|
|
@@ -45,7 +45,7 @@ Object {
|
|
|
45
45
|
"allowSubscriptions": "followers",
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
48
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
49
49
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
50
50
|
"description": "its me!",
|
|
51
51
|
"did": "user(0)",
|
|
@@ -123,7 +123,7 @@ Object {
|
|
|
123
123
|
"allowSubscriptions": "followers",
|
|
124
124
|
},
|
|
125
125
|
},
|
|
126
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(4)/cids(1)
|
|
126
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(4)/cids(1)",
|
|
127
127
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
128
128
|
"description": "hi im bob label_me",
|
|
129
129
|
"did": "user(3)",
|
|
@@ -184,7 +184,7 @@ Object {
|
|
|
184
184
|
"allowSubscriptions": "followers",
|
|
185
185
|
},
|
|
186
186
|
},
|
|
187
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
187
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
188
188
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
189
189
|
"did": "user(0)",
|
|
190
190
|
"displayName": "ali",
|
|
@@ -219,7 +219,7 @@ Object {
|
|
|
219
219
|
"allowSubscriptions": "followers",
|
|
220
220
|
},
|
|
221
221
|
},
|
|
222
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
222
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
223
223
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
224
224
|
"description": "its me!",
|
|
225
225
|
"did": "user(0)",
|
|
@@ -299,7 +299,7 @@ Object {
|
|
|
299
299
|
"allowSubscriptions": "followers",
|
|
300
300
|
},
|
|
301
301
|
},
|
|
302
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(4)/cids(1)
|
|
302
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(4)/cids(1)",
|
|
303
303
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
304
304
|
"description": "hi im bob label_me",
|
|
305
305
|
"did": "user(3)",
|
|
@@ -362,7 +362,7 @@ Object {
|
|
|
362
362
|
"allowSubscriptions": "followers",
|
|
363
363
|
},
|
|
364
364
|
},
|
|
365
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
365
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
366
366
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
367
367
|
"did": "user(0)",
|
|
368
368
|
"displayName": "ali",
|
|
@@ -397,7 +397,7 @@ Object {
|
|
|
397
397
|
"allowSubscriptions": "followers",
|
|
398
398
|
},
|
|
399
399
|
},
|
|
400
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)
|
|
400
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(1)/cids(1)",
|
|
401
401
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
402
402
|
"description": "its me!",
|
|
403
403
|
"did": "user(0)",
|
|
@@ -483,7 +483,7 @@ Object {
|
|
|
483
483
|
"allowSubscriptions": "followers",
|
|
484
484
|
},
|
|
485
485
|
},
|
|
486
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(5)/cids(1)
|
|
486
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(5)/cids(1)",
|
|
487
487
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
488
488
|
"description": "hi im bob label_me",
|
|
489
489
|
"did": "user(4)",
|
|
@@ -14,7 +14,7 @@ Array [
|
|
|
14
14
|
"lists": 0,
|
|
15
15
|
"starterPacks": 0,
|
|
16
16
|
},
|
|
17
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(3)/cids(0)
|
|
17
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(3)/cids(0)",
|
|
18
18
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
19
19
|
"description": "its me!",
|
|
20
20
|
"did": "user(0)",
|
|
@@ -199,7 +199,7 @@ Array [
|
|
|
199
199
|
"lists": 0,
|
|
200
200
|
"starterPacks": 0,
|
|
201
201
|
},
|
|
202
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(3)/cids(0)
|
|
202
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(3)/cids(0)",
|
|
203
203
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
204
204
|
"description": "its me!",
|
|
205
205
|
"did": "user(0)",
|
|
@@ -92,7 +92,7 @@ Array [
|
|
|
92
92
|
"lists": 0,
|
|
93
93
|
"starterPacks": 0,
|
|
94
94
|
},
|
|
95
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(6)/cids(0)
|
|
95
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(6)/cids(0)",
|
|
96
96
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
97
97
|
"description": "its me!",
|
|
98
98
|
"did": "user(5)",
|
|
@@ -141,7 +141,7 @@ Array [
|
|
|
141
141
|
"lists": 0,
|
|
142
142
|
"starterPacks": 0,
|
|
143
143
|
},
|
|
144
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(8)/cids(0)
|
|
144
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(8)/cids(0)",
|
|
145
145
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
146
146
|
"description": "hi im bob label_me",
|
|
147
147
|
"did": "user(7)",
|
|
@@ -273,7 +273,7 @@ Array [
|
|
|
273
273
|
"lists": 0,
|
|
274
274
|
"starterPacks": 0,
|
|
275
275
|
},
|
|
276
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(6)/cids(0)
|
|
276
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(6)/cids(0)",
|
|
277
277
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
278
278
|
"description": "its me!",
|
|
279
279
|
"did": "user(5)",
|
|
@@ -322,7 +322,7 @@ Array [
|
|
|
322
322
|
"lists": 0,
|
|
323
323
|
"starterPacks": 0,
|
|
324
324
|
},
|
|
325
|
-
"avatar": "https://bsky.public.url/img/avatar/plain/user(8)/cids(0)
|
|
325
|
+
"avatar": "https://bsky.public.url/img/avatar/plain/user(8)/cids(0)",
|
|
326
326
|
"createdAt": "1970-01-01T00:00:00.000Z",
|
|
327
327
|
"description": "hi im bob label_me",
|
|
328
328
|
"did": "user(7)",
|