@atproto/ozone 0.0.17 → 0.1.0

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.
@@ -2206,6 +2206,11 @@ export declare const schemaDict: {
2206
2206
  description: string;
2207
2207
  ref: string;
2208
2208
  };
2209
+ contact: {
2210
+ type: string;
2211
+ description: string;
2212
+ ref: string;
2213
+ };
2209
2214
  did: {
2210
2215
  type: string;
2211
2216
  format: string;
@@ -2225,6 +2230,14 @@ export declare const schemaDict: {
2225
2230
  };
2226
2231
  };
2227
2232
  };
2233
+ contact: {
2234
+ type: string;
2235
+ properties: {
2236
+ email: {
2237
+ type: string;
2238
+ };
2239
+ };
2240
+ };
2228
2241
  };
2229
2242
  };
2230
2243
  ComAtprotoServerGetAccountInviteCodes: {
@@ -9,6 +9,7 @@ export interface OutputSchema {
9
9
  phoneVerificationRequired?: boolean;
10
10
  availableUserDomains: string[];
11
11
  links?: Links;
12
+ contact?: Contact;
12
13
  did: string;
13
14
  [k: string]: unknown;
14
15
  }
@@ -40,3 +41,9 @@ export interface Links {
40
41
  }
41
42
  export declare function isLinks(v: unknown): v is Links;
42
43
  export declare function validateLinks(v: unknown): ValidationResult;
44
+ export interface Contact {
45
+ email?: string;
46
+ [k: string]: unknown;
47
+ }
48
+ export declare function isContact(v: unknown): v is Contact;
49
+ export declare function validateContact(v: unknown): ValidationResult;
@@ -180,6 +180,8 @@ export declare class ModerationService {
180
180
  subject: string;
181
181
  }): Promise<void>;
182
182
  }
183
+ export declare const TAKEDOWN_LABEL = "!takedown";
184
+ export declare const SUSPEND_LABEL = "!suspend";
183
185
  export type TakedownSubjects = {
184
186
  did: string;
185
187
  subjects: (RepoRef | RepoBlobRef | StrongRef)[];
@@ -17,5 +17,3 @@ export type ModerationSubjectStatusRowWithHandle = ModerationSubjectStatusRow &
17
17
  handle: string | null;
18
18
  };
19
19
  export type ModEventType = ToolsOzoneModerationDefs.ModEventTakedown | ToolsOzoneModerationDefs.ModEventAcknowledge | ToolsOzoneModerationDefs.ModEventEscalate | ToolsOzoneModerationDefs.ModEventComment | ToolsOzoneModerationDefs.ModEventLabel | ToolsOzoneModerationDefs.ModEventReport | ToolsOzoneModerationDefs.ModEventMute | ToolsOzoneModerationDefs.ModEventReverseTakedown | ToolsOzoneModerationDefs.ModEventTag;
20
- export declare const UNSPECCED_TAKEDOWN_LABEL = "!unspecced-takedown";
21
- export declare const UNSPECCED_TAKEDOWN_BLOBS_LABEL = "!unspecced-takedown-blobs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/ozone",
3
- "version": "0.0.17",
3
+ "version": "0.1.0",
4
4
  "license": "MIT",
5
5
  "description": "Backend service for moderating the Bluesky network.",
6
6
  "keywords": [
@@ -30,7 +30,7 @@
30
30
  "pino-http": "^8.2.1",
31
31
  "typed-emitter": "^2.1.0",
32
32
  "uint8arrays": "3.0.0",
33
- "@atproto/api": "^0.11.0",
33
+ "@atproto/api": "^0.11.1",
34
34
  "@atproto/common": "^0.3.4",
35
35
  "@atproto/crypto": "^0.3.0",
36
36
  "@atproto/identity": "^0.3.3",
@@ -47,10 +47,10 @@
47
47
  "@types/qs": "^6.9.7",
48
48
  "axios": "^0.27.2",
49
49
  "nodemailer": "^6.8.0",
50
- "@atproto/api": "^0.11.0",
51
- "@atproto/dev-env": "^0.2.38",
50
+ "@atproto/api": "^0.11.1",
51
+ "@atproto/dev-env": "^0.2.39",
52
52
  "@atproto/lex-cli": "^0.3.2",
53
- "@atproto/pds": "^0.4.6",
53
+ "@atproto/pds": "^0.4.7",
54
54
  "@atproto/xrpc": "^0.4.3"
55
55
  },
56
56
  "scripts": {
@@ -1,30 +1,18 @@
1
1
  import { Server } from '../../lexicon'
2
2
  import AppContext from '../../context'
3
- import {
4
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
5
- UNSPECCED_TAKEDOWN_LABEL,
6
- } from '../../mod-service/types'
7
3
 
8
4
  export default function (server: Server, ctx: AppContext) {
9
5
  server.com.atproto.temp.fetchLabels({
10
6
  auth: ctx.authVerifier.standardOptionalOrAdminToken,
11
- handler: async ({ auth, params }) => {
7
+ handler: async ({ params }) => {
12
8
  const { limit } = params
13
9
  const since =
14
10
  params.since !== undefined ? new Date(params.since).toISOString() : ''
15
- const includeUnspeccedTakedowns =
16
- auth.credentials.type === 'none' ? false : auth.credentials.isAdmin
17
11
  const labelRes = await ctx.db.db
18
12
  .selectFrom('label')
19
13
  .selectAll()
20
14
  .orderBy('label.cts', 'asc')
21
15
  .where('cts', '>', since)
22
- .if(!includeUnspeccedTakedowns, (q) =>
23
- q.where('label.val', 'not in', [
24
- UNSPECCED_TAKEDOWN_LABEL,
25
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
26
- ]),
27
- )
28
16
  .limit(limit)
29
17
  .execute()
30
18
 
@@ -2420,6 +2420,11 @@ export const schemaDict = {
2420
2420
  description: 'URLs of service policy documents.',
2421
2421
  ref: 'lex:com.atproto.server.describeServer#links',
2422
2422
  },
2423
+ contact: {
2424
+ type: 'ref',
2425
+ description: 'Contact information',
2426
+ ref: 'lex:com.atproto.server.describeServer#contact',
2427
+ },
2423
2428
  did: {
2424
2429
  type: 'string',
2425
2430
  format: 'did',
@@ -2439,6 +2444,14 @@ export const schemaDict = {
2439
2444
  },
2440
2445
  },
2441
2446
  },
2447
+ contact: {
2448
+ type: 'object',
2449
+ properties: {
2450
+ email: {
2451
+ type: 'string',
2452
+ },
2453
+ },
2454
+ },
2442
2455
  },
2443
2456
  },
2444
2457
  ComAtprotoServerGetAccountInviteCodes: {
@@ -20,6 +20,7 @@ export interface OutputSchema {
20
20
  /** List of domain suffixes that can be used in account handles. */
21
21
  availableUserDomains: string[]
22
22
  links?: Links
23
+ contact?: Contact
23
24
  did: string
24
25
  [k: string]: unknown
25
26
  }
@@ -66,3 +67,20 @@ export function isLinks(v: unknown): v is Links {
66
67
  export function validateLinks(v: unknown): ValidationResult {
67
68
  return lexicons.validate('com.atproto.server.describeServer#links', v)
68
69
  }
70
+
71
+ export interface Contact {
72
+ email?: string
73
+ [k: string]: unknown
74
+ }
75
+
76
+ export function isContact(v: unknown): v is Contact {
77
+ return (
78
+ isObj(v) &&
79
+ hasProp(v, '$type') &&
80
+ v.$type === 'com.atproto.server.describeServer#contact'
81
+ )
82
+ }
83
+
84
+ export function validateContact(v: unknown): ValidationResult {
85
+ return lexicons.validate('com.atproto.server.describeServer#contact', v)
86
+ }
@@ -29,8 +29,6 @@ import {
29
29
  ModerationEventRow,
30
30
  ModerationSubjectStatusRow,
31
31
  ReversibleModerationEvent,
32
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
33
- UNSPECCED_TAKEDOWN_LABEL,
34
32
  } from './types'
35
33
  import { ModerationEvent } from '../db/schema/moderation_event'
36
34
  import { StatusKeyset, TimeIdKeyset, paginate } from '../db/pagination'
@@ -480,8 +478,10 @@ export class ModerationService {
480
478
  )
481
479
  .returning('id')
482
480
  .execute()
481
+
482
+ const takedownLabel = isSuspend ? SUSPEND_LABEL : TAKEDOWN_LABEL
483
483
  await this.formatAndCreateLabels(subject.did, null, {
484
- create: [UNSPECCED_TAKEDOWN_LABEL],
484
+ create: [takedownLabel],
485
485
  })
486
486
 
487
487
  this.db.onCommit(() => {
@@ -506,8 +506,18 @@ export class ModerationService {
506
506
  })
507
507
  .returning('id')
508
508
  .execute()
509
+
510
+ const existingTakedownLabels = await this.db.db
511
+ .selectFrom('label')
512
+ .where('label.uri', '=', subject.did)
513
+ .where('label.val', 'in', [TAKEDOWN_LABEL, SUSPEND_LABEL])
514
+ .where('neg', '=', false)
515
+ .selectAll()
516
+ .execute()
517
+
518
+ const takedownVals = existingTakedownLabels.map((row) => row.val)
509
519
  await this.formatAndCreateLabels(subject.did, null, {
510
- negate: [UNSPECCED_TAKEDOWN_LABEL],
520
+ negate: takedownVals,
511
521
  })
512
522
 
513
523
  this.db.onCommit(() => {
@@ -521,44 +531,12 @@ export class ModerationService {
521
531
 
522
532
  async takedownRecord(subject: RecordSubject, takedownId: number) {
523
533
  this.db.assertTransaction()
524
- const takedownRef = `BSKY-TAKEDOWN-${takedownId}`
525
- const values = this.eventPusher.takedowns.map((eventType) => ({
526
- eventType,
527
- subjectDid: subject.did,
528
- subjectUri: subject.uri,
529
- subjectCid: subject.cid,
530
- takedownRef,
531
- }))
532
- const blobCids = subject.blobCids
533
- const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
534
- if (blobCids && blobCids.length > 0) {
535
- labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
536
- }
537
- const recordEvts = await this.db.db
538
- .insertInto('record_push_event')
539
- .values(values)
540
- .onConflict((oc) =>
541
- oc.columns(['subjectUri', 'eventType']).doUpdateSet({
542
- takedownRef,
543
- confirmedAt: null,
544
- attempts: 0,
545
- lastAttempted: null,
546
- }),
547
- )
548
- .returning('id')
549
- .execute()
550
534
  await this.formatAndCreateLabels(subject.uri, subject.cid, {
551
- create: labels,
552
- })
553
-
554
- this.db.onCommit(() => {
555
- this.backgroundQueue.add(async () => {
556
- await Promise.all(
557
- recordEvts.map((evt) => this.eventPusher.attemptRecordEvent(evt.id)),
558
- )
559
- })
535
+ create: [TAKEDOWN_LABEL],
560
536
  })
561
537
 
538
+ const takedownRef = `BSKY-TAKEDOWN-${takedownId}`
539
+ const blobCids = subject.blobCids
562
540
  if (blobCids && blobCids.length > 0) {
563
541
  const blobValues: Insertable<BlobPushEvent>[] = []
564
542
  for (const eventType of this.eventPusher.takedowns) {
@@ -613,37 +591,11 @@ export class ModerationService {
613
591
 
614
592
  async reverseTakedownRecord(subject: RecordSubject) {
615
593
  this.db.assertTransaction()
616
- const labels: string[] = [UNSPECCED_TAKEDOWN_LABEL]
617
- const blobCids = subject.blobCids
618
- if (blobCids && blobCids.length > 0) {
619
- labels.push(UNSPECCED_TAKEDOWN_BLOBS_LABEL)
620
- }
621
- const recordEvts = await this.db.db
622
- .updateTable('record_push_event')
623
- .where('eventType', 'in', TAKEDOWNS)
624
- .where('subjectDid', '=', subject.did)
625
- .where('subjectUri', '=', subject.uri)
626
- .set({
627
- takedownRef: null,
628
- confirmedAt: null,
629
- attempts: 0,
630
- lastAttempted: null,
631
- })
632
- .returning('id')
633
- .execute()
634
594
  await this.formatAndCreateLabels(subject.uri, subject.cid, {
635
- negate: labels,
636
- }),
637
- this.db.onCommit(() => {
638
- this.backgroundQueue.add(async () => {
639
- await Promise.all(
640
- recordEvts.map((evt) =>
641
- this.eventPusher.attemptRecordEvent(evt.id),
642
- ),
643
- )
644
- })
645
- })
595
+ negate: [TAKEDOWN_LABEL],
596
+ })
646
597
 
598
+ const blobCids = subject.blobCids
647
599
  if (blobCids && blobCids.length > 0) {
648
600
  const blobEvts = await this.db.db
649
601
  .updateTable('blob_push_event')
@@ -907,6 +859,9 @@ export class ModerationService {
907
859
  id: sql`${excluded('id')}`,
908
860
  neg: sql`${excluded('neg')}`,
909
861
  cts: sql`${excluded('cts')}`,
862
+ exp: sql`${excluded('exp')}`,
863
+ sig: sql`${excluded('sig')}`,
864
+ signingKeyId: sql`${excluded('signingKeyId')}`,
910
865
  }),
911
866
  )
912
867
  .returningAll()
@@ -960,6 +915,9 @@ const isSafeUrl = (url: URL) => {
960
915
 
961
916
  const TAKEDOWNS = ['pds_takedown' as const, 'appview_takedown' as const]
962
917
 
918
+ export const TAKEDOWN_LABEL = '!takedown'
919
+ export const SUSPEND_LABEL = '!suspend'
920
+
963
921
  export type TakedownSubjects = {
964
922
  did: string
965
923
  subjects: (RepoRef | RepoBlobRef | StrongRef)[]
@@ -31,7 +31,3 @@ export type ModEventType =
31
31
  | ToolsOzoneModerationDefs.ModEventMute
32
32
  | ToolsOzoneModerationDefs.ModEventReverseTakedown
33
33
  | ToolsOzoneModerationDefs.ModEventTag
34
-
35
- export const UNSPECCED_TAKEDOWN_LABEL = '!unspecced-takedown'
36
-
37
- export const UNSPECCED_TAKEDOWN_BLOBS_LABEL = '!unspecced-takedown-blobs'
@@ -12,7 +12,7 @@ export const formatLabel = (row: LabelRow): Label => {
12
12
  uri: row.uri,
13
13
  cid: row.cid === '' ? undefined : row.cid,
14
14
  val: row.val,
15
- neg: row.neg,
15
+ neg: row.neg === true ? true : undefined,
16
16
  cts: row.cts,
17
17
  exp: row.exp ?? undefined,
18
18
  sig: row.sig ? new Uint8Array(row.sig) : undefined,
@@ -573,6 +573,6 @@ export function getSelfLabels(details: {
573
573
  ? normalizeDatetimeAlways(record.createdAt)
574
574
  : new Date(0).toISOString()
575
575
  return record.labels.values.map(({ val }) => {
576
- return { src, uri, cid, val, cts, neg: false }
576
+ return { src, uri, cid, val, cts }
577
577
  })
578
578
  }
@@ -10,19 +10,17 @@ Object {
10
10
  Object {
11
11
  "cid": "cids(0)",
12
12
  "cts": "1970-01-01T00:00:00.000Z",
13
- "neg": false,
14
13
  "sig": Object {
15
14
  "$bytes": "sig(0)",
16
15
  },
17
16
  "src": "user(2)",
18
17
  "uri": "record(0)",
19
- "val": "!unspecced-takedown",
18
+ "val": "!takedown",
20
19
  "ver": 1,
21
20
  },
22
21
  Object {
23
22
  "cid": "cids(0)",
24
23
  "cts": "1970-01-01T00:00:00.000Z",
25
- "neg": false,
26
24
  "src": "user(0)",
27
25
  "uri": "record(0)",
28
26
  "val": "self-label",
@@ -111,19 +109,17 @@ Object {
111
109
  Object {
112
110
  "cid": "cids(0)",
113
111
  "cts": "1970-01-01T00:00:00.000Z",
114
- "neg": false,
115
112
  "sig": Object {
116
113
  "$bytes": "sig(0)",
117
114
  },
118
115
  "src": "user(2)",
119
116
  "uri": "record(0)",
120
- "val": "!unspecced-takedown",
117
+ "val": "!takedown",
121
118
  "ver": 1,
122
119
  },
123
120
  Object {
124
121
  "cid": "cids(0)",
125
122
  "cts": "1970-01-01T00:00:00.000Z",
126
- "neg": false,
127
123
  "src": "user(0)",
128
124
  "uri": "record(0)",
129
125
  "val": "self-label",
@@ -11,13 +11,12 @@ Object {
11
11
  "labels": Array [
12
12
  Object {
13
13
  "cts": "1970-01-01T00:00:00.000Z",
14
- "neg": false,
15
14
  "sig": Object {
16
15
  "$bytes": "sig(0)",
17
16
  },
18
17
  "src": "user(2)",
19
18
  "uri": "user(0)",
20
- "val": "!unspecced-takedown",
19
+ "val": "!takedown",
21
20
  "ver": 1,
22
21
  },
23
22
  ],
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  TestNetwork,
3
+ TestOzone,
3
4
  ImageRef,
4
5
  RecordRef,
5
6
  SeedClient,
@@ -20,12 +21,8 @@ import {
20
21
  REVIEWESCALATED,
21
22
  } from '../src/lexicon/types/tools/ozone/moderation/defs'
22
23
  import { EventReverser } from '../src'
23
- import { TestOzone } from '@atproto/dev-env/src/ozone'
24
24
  import { ImageInvalidator } from '../src/image-invalidator'
25
- import {
26
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
27
- UNSPECCED_TAKEDOWN_LABEL,
28
- } from '../src/mod-service/types'
25
+ import { TAKEDOWN_LABEL } from '../src/mod-service'
29
26
 
30
27
  describe('moderation', () => {
31
28
  let network: TestNetwork
@@ -542,10 +539,7 @@ describe('moderation', () => {
542
539
  )
543
540
  expect(bskyRes1.data.takedown?.applied).toBe(true)
544
541
 
545
- const takedownLabel1 = await getLabel(
546
- sc.dids.bob,
547
- UNSPECCED_TAKEDOWN_LABEL,
548
- )
542
+ const takedownLabel1 = await getLabel(sc.dids.bob, TAKEDOWN_LABEL)
549
543
  expect(takedownLabel1).toBeDefined()
550
544
 
551
545
  // cleanup
@@ -570,52 +564,7 @@ describe('moderation', () => {
570
564
  )
571
565
  expect(bskyRes2.data.takedown?.applied).toBe(false)
572
566
 
573
- const takedownLabel2 = await getLabel(
574
- sc.dids.bob,
575
- UNSPECCED_TAKEDOWN_LABEL,
576
- )
577
- expect(takedownLabel2).toBeUndefined()
578
- })
579
-
580
- it('fans out record takedowns', async () => {
581
- const post = sc.posts[sc.dids.bob][0].ref
582
- const uri = post.uriStr
583
- await modClient.performTakedown({
584
- subject: recordSubject(post),
585
- })
586
- await ozone.processAll()
587
-
588
- const pdsRes1 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
589
- { uri },
590
- { headers: network.pds.adminAuthHeaders() },
591
- )
592
- expect(pdsRes1.data.takedown?.applied).toBe(true)
593
-
594
- const bskyRes1 = await bskyAgent.api.com.atproto.admin.getSubjectStatus(
595
- { uri },
596
- { headers: network.bsky.adminAuthHeaders() },
597
- )
598
- expect(bskyRes1.data.takedown?.applied).toBe(true)
599
-
600
- const takedownLabel1 = await getLabel(uri, UNSPECCED_TAKEDOWN_LABEL)
601
- expect(takedownLabel1).toBeDefined()
602
-
603
- // cleanup
604
- await modClient.performReverseTakedown({ subject: recordSubject(post) })
605
- await ozone.processAll()
606
-
607
- const pdsRes2 = await pdsAgent.api.com.atproto.admin.getSubjectStatus(
608
- { uri },
609
- { headers: network.pds.adminAuthHeaders() },
610
- )
611
- expect(pdsRes2.data.takedown?.applied).toBe(false)
612
- const bskyRes2 = await bskyAgent.api.com.atproto.admin.getSubjectStatus(
613
- { uri },
614
- { headers: network.bsky.adminAuthHeaders() },
615
- )
616
- expect(bskyRes2.data.takedown?.applied).toBe(false)
617
-
618
- const takedownLabel2 = await getLabel(uri, UNSPECCED_TAKEDOWN_LABEL)
567
+ const takedownLabel2 = await getLabel(sc.dids.bob, TAKEDOWN_LABEL)
619
568
  expect(takedownLabel2).toBeUndefined()
620
569
  })
621
570
 
@@ -713,22 +662,6 @@ describe('moderation', () => {
713
662
  })
714
663
  })
715
664
 
716
- it('serves label when authed', async () => {
717
- const { data: unauthed } = await agent.api.com.atproto.temp.fetchLabels(
718
- {},
719
- )
720
- expect(unauthed.labels.map((l) => l.val)).not.toContain(
721
- UNSPECCED_TAKEDOWN_LABEL,
722
- )
723
- const { data: authed } = await agent.api.com.atproto.temp.fetchLabels(
724
- {},
725
- { headers: network.bsky.adminAuthHeaders() },
726
- )
727
- expect(authed.labels.map((l) => l.val)).toContain(
728
- UNSPECCED_TAKEDOWN_LABEL,
729
- )
730
- })
731
-
732
665
  async function emitLabelEvent(
733
666
  opts: Partial<ToolsOzoneModerationEmitEvent.InputSchema> & {
734
667
  subject: ToolsOzoneModerationEmitEvent.InputSchema['subject']
@@ -860,14 +793,6 @@ describe('moderation', () => {
860
793
  expect(res.data.takedown?.applied).toBe(true)
861
794
  })
862
795
 
863
- it('creates a takedown blobs label', async () => {
864
- const label = await getLabel(
865
- post.ref.uriStr,
866
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
867
- )
868
- expect(label).toBeDefined()
869
- })
870
-
871
796
  it('restores blob when action is reversed.', async () => {
872
797
  await modClient.performReverseTakedown({
873
798
  subject: recordSubject(post.ref),
@@ -898,30 +823,6 @@ describe('moderation', () => {
898
823
  )
899
824
  expect(res.data.takedown?.applied).toBe(false)
900
825
  })
901
-
902
- it('serves label when authed', async () => {
903
- const { data: unauthed } = await agent.api.com.atproto.temp.fetchLabels(
904
- {},
905
- )
906
- expect(unauthed.labels.map((l) => l.val)).not.toContain(
907
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
908
- )
909
- const { data: authed } = await agent.api.com.atproto.temp.fetchLabels(
910
- {},
911
- { headers: network.bsky.adminAuthHeaders() },
912
- )
913
- expect(authed.labels.map((l) => l.val)).toContain(
914
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
915
- )
916
- })
917
-
918
- it('negates takedown blobs label on reversal', async () => {
919
- const label = await getLabel(
920
- post.ref.uriStr,
921
- UNSPECCED_TAKEDOWN_BLOBS_LABEL,
922
- )
923
- expect(label).toBeUndefined()
924
- })
925
826
  })
926
827
  })
927
828
 
@@ -30,42 +30,36 @@ describe('ozone query labels', () => {
30
30
  src: EXAMPLE_LABELER,
31
31
  uri: 'did:example:blah',
32
32
  val: 'spam',
33
- neg: false,
34
33
  cts: new Date().toISOString(),
35
34
  },
36
35
  {
37
36
  src: EXAMPLE_LABELER,
38
37
  uri: 'did:example:blah',
39
38
  val: 'impersonation',
40
- neg: false,
41
39
  cts: new Date().toISOString(),
42
40
  },
43
41
  {
44
42
  src: EXAMPLE_LABELER,
45
43
  uri: 'at://did:example:blah/app.bsky.feed.post/1234abcde',
46
44
  val: 'spam',
47
- neg: false,
48
45
  cts: new Date().toISOString(),
49
46
  },
50
47
  {
51
48
  src: EXAMPLE_LABELER,
52
49
  uri: 'at://did:example:blah/app.bsky.feed.post/1234abcfg',
53
50
  val: 'spam',
54
- neg: false,
55
51
  cts: new Date().toISOString(),
56
52
  },
57
53
  {
58
54
  src: EXAMPLE_LABELER,
59
55
  uri: 'at://did:example:blah/app.bsky.actor.profile/self',
60
56
  val: 'spam',
61
- neg: false,
62
57
  cts: new Date().toISOString(),
63
58
  },
64
59
  {
65
60
  src: EXAMPLE_LABELER,
66
61
  uri: 'did:example:thing',
67
62
  val: 'spam',
68
- neg: false,
69
63
  cts: new Date().toISOString(),
70
64
  },
71
65
  ]
@@ -37,6 +37,7 @@ describe('sequencer', () => {
37
37
  return {
38
38
  id: e.seq,
39
39
  ...label,
40
+ neg: !!label.neg,
40
41
  cid: label.cid ? label.cid : '',
41
42
  exp: null,
42
43
  sig: label.sig ? Buffer.from(label.sig) : null,