@atproto/pds 0.3.8 → 0.3.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -124,6 +124,7 @@ export declare const COM_ATPROTO_MODERATION: {
124
124
  DefsReasonSexual: string;
125
125
  DefsReasonRude: string;
126
126
  DefsReasonOther: string;
127
+ DefsReasonAppeal: string;
127
128
  };
128
129
  export declare const APP_BSKY_GRAPH: {
129
130
  DefsModlist: string;
@@ -177,9 +177,18 @@ export declare const schemaDict: {
177
177
  type: string;
178
178
  format: string;
179
179
  };
180
+ lastAppealedAt: {
181
+ type: string;
182
+ format: string;
183
+ description: string;
184
+ };
180
185
  takendown: {
181
186
  type: string;
182
187
  };
188
+ appealed: {
189
+ type: string;
190
+ description: string;
191
+ };
183
192
  suspendUntil: {
184
193
  type: string;
185
194
  format: string;
@@ -606,6 +615,16 @@ export declare const schemaDict: {
606
615
  };
607
616
  };
608
617
  };
618
+ modEventResolveAppeal: {
619
+ type: string;
620
+ description: string;
621
+ properties: {
622
+ comment: {
623
+ type: string;
624
+ description: string;
625
+ };
626
+ };
627
+ };
609
628
  modEventComment: {
610
629
  type: string;
611
630
  description: string;
@@ -705,6 +724,10 @@ export declare const schemaDict: {
705
724
  type: string;
706
725
  description: string;
707
726
  };
727
+ comment: {
728
+ type: string;
729
+ description: string;
730
+ };
708
731
  };
709
732
  };
710
733
  };
@@ -1214,6 +1237,10 @@ export declare const schemaDict: {
1214
1237
  type: string;
1215
1238
  description: string;
1216
1239
  };
1240
+ appealed: {
1241
+ type: string;
1242
+ description: string;
1243
+ };
1217
1244
  limit: {
1218
1245
  type: string;
1219
1246
  minimum: number;
@@ -1324,6 +1351,10 @@ export declare const schemaDict: {
1324
1351
  type: string;
1325
1352
  format: string;
1326
1353
  };
1354
+ comment: {
1355
+ type: string;
1356
+ description: string;
1357
+ };
1327
1358
  };
1328
1359
  };
1329
1360
  };
@@ -1777,6 +1808,10 @@ export declare const schemaDict: {
1777
1808
  type: string;
1778
1809
  description: string;
1779
1810
  };
1811
+ reasonAppeal: {
1812
+ type: string;
1813
+ description: string;
1814
+ };
1780
1815
  };
1781
1816
  };
1782
1817
  ComAtprotoRepoApplyWrites: {
@@ -31,7 +31,7 @@ export declare function isModEventView(v: unknown): v is ModEventView;
31
31
  export declare function validateModEventView(v: unknown): ValidationResult;
32
32
  export interface ModEventViewDetail {
33
33
  id: number;
34
- event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | {
34
+ event: ModEventTakedown | ModEventReverseTakedown | ModEventComment | ModEventReport | ModEventLabel | ModEventAcknowledge | ModEventEscalate | ModEventMute | ModEventResolveAppeal | {
35
35
  $type: string;
36
36
  [k: string]: unknown;
37
37
  };
@@ -78,7 +78,9 @@ export interface SubjectStatusView {
78
78
  lastReviewedBy?: string;
79
79
  lastReviewedAt?: string;
80
80
  lastReportedAt?: string;
81
+ lastAppealedAt?: string;
81
82
  takendown?: boolean;
83
+ appealed?: boolean;
82
84
  suspendUntil?: string;
83
85
  [k: string]: unknown;
84
86
  }
@@ -254,6 +256,12 @@ export interface ModEventReverseTakedown {
254
256
  }
255
257
  export declare function isModEventReverseTakedown(v: unknown): v is ModEventReverseTakedown;
256
258
  export declare function validateModEventReverseTakedown(v: unknown): ValidationResult;
259
+ export interface ModEventResolveAppeal {
260
+ comment?: string;
261
+ [k: string]: unknown;
262
+ }
263
+ export declare function isModEventResolveAppeal(v: unknown): v is ModEventResolveAppeal;
264
+ export declare function validateModEventResolveAppeal(v: unknown): ValidationResult;
257
265
  export interface ModEventComment {
258
266
  comment: string;
259
267
  sticky?: boolean;
@@ -303,6 +311,7 @@ export declare function isModEventUnmute(v: unknown): v is ModEventUnmute;
303
311
  export declare function validateModEventUnmute(v: unknown): ValidationResult;
304
312
  export interface ModEventEmail {
305
313
  subjectLine: string;
314
+ comment?: string;
306
315
  [k: string]: unknown;
307
316
  }
308
317
  export declare function isModEventEmail(v: unknown): v is ModEventEmail;
@@ -15,6 +15,7 @@ export interface QueryParams {
15
15
  sortField: 'lastReviewedAt' | 'lastReportedAt';
16
16
  sortDirection: 'asc' | 'desc';
17
17
  takendown?: boolean;
18
+ appealed?: boolean;
18
19
  limit: number;
19
20
  cursor?: string;
20
21
  }
@@ -7,6 +7,7 @@ export interface InputSchema {
7
7
  content: string;
8
8
  subject?: string;
9
9
  senderDid: string;
10
+ comment?: string;
10
11
  [k: string]: unknown;
11
12
  }
12
13
  export interface OutputSchema {
@@ -1,7 +1,8 @@
1
- export declare type ReasonType = 'com.atproto.moderation.defs#reasonSpam' | 'com.atproto.moderation.defs#reasonViolation' | 'com.atproto.moderation.defs#reasonMisleading' | 'com.atproto.moderation.defs#reasonSexual' | 'com.atproto.moderation.defs#reasonRude' | 'com.atproto.moderation.defs#reasonOther' | (string & {});
1
+ export declare type ReasonType = 'com.atproto.moderation.defs#reasonSpam' | 'com.atproto.moderation.defs#reasonViolation' | 'com.atproto.moderation.defs#reasonMisleading' | 'com.atproto.moderation.defs#reasonSexual' | 'com.atproto.moderation.defs#reasonRude' | 'com.atproto.moderation.defs#reasonOther' | 'com.atproto.moderation.defs#reasonAppeal' | (string & {});
2
2
  export declare const REASONSPAM = "com.atproto.moderation.defs#reasonSpam";
3
3
  export declare const REASONVIOLATION = "com.atproto.moderation.defs#reasonViolation";
4
4
  export declare const REASONMISLEADING = "com.atproto.moderation.defs#reasonMisleading";
5
5
  export declare const REASONSEXUAL = "com.atproto.moderation.defs#reasonSexual";
6
6
  export declare const REASONRUDE = "com.atproto.moderation.defs#reasonRude";
7
7
  export declare const REASONOTHER = "com.atproto.moderation.defs#reasonOther";
8
+ export declare const REASONAPPEAL = "com.atproto.moderation.defs#reasonAppeal";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/pds",
3
- "version": "0.3.8",
3
+ "version": "0.3.10",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of atproto Personal Data Server (PDS)",
6
6
  "keywords": [
@@ -16,7 +16,7 @@
16
16
  "main": "dist/index.js",
17
17
  "bin": "dist/bin.js",
18
18
  "dependencies": {
19
- "@did-plc/lib": "^0.0.1",
19
+ "@did-plc/lib": "^0.0.4",
20
20
  "better-sqlite3": "^7.6.2",
21
21
  "bytes": "^3.1.2",
22
22
  "compression": "^1.7.4",
@@ -44,7 +44,7 @@
44
44
  "typed-emitter": "^2.1.0",
45
45
  "uint8arrays": "3.0.0",
46
46
  "zod": "^3.21.4",
47
- "@atproto/api": "^0.7.3",
47
+ "@atproto/api": "^0.8.0",
48
48
  "@atproto/aws": "^0.1.6",
49
49
  "@atproto/common": "^0.3.3",
50
50
  "@atproto/crypto": "^0.3.0",
@@ -68,9 +68,9 @@
68
68
  "axios": "^0.27.2",
69
69
  "get-port": "^6.1.2",
70
70
  "ws": "^8.12.0",
71
- "@atproto/api": "^0.7.3",
72
- "@atproto/bsky": "^0.0.20",
73
- "@atproto/dev-env": "^0.2.20",
71
+ "@atproto/api": "^0.8.0",
72
+ "@atproto/bsky": "^0.0.22",
73
+ "@atproto/dev-env": "^0.2.22",
74
74
  "@atproto/lex-cli": "^0.2.5"
75
75
  },
76
76
  "scripts": {
@@ -11,7 +11,7 @@ export default function (server: Server, ctx: AppContext) {
11
11
  'Account invites are managed by the entryway service',
12
12
  )
13
13
  }
14
- if (!auth.credentials.admin) {
14
+ if (!auth.credentials.moderator) {
15
15
  throw new AuthRequiredError('Insufficient privileges')
16
16
  }
17
17
  const { account } = input.body
@@ -11,7 +11,7 @@ export default function (server: Server, ctx: AppContext) {
11
11
  'Account invites are managed by the entryway service',
12
12
  )
13
13
  }
14
- if (!auth.credentials.admin) {
14
+ if (!auth.credentials.moderator) {
15
15
  throw new AuthRequiredError('Insufficient privileges')
16
16
  }
17
17
  const { codes = [], accounts = [] } = input.body
@@ -11,7 +11,7 @@ export default function (server: Server, ctx: AppContext) {
11
11
  'Account invites are managed by the entryway service',
12
12
  )
13
13
  }
14
- if (!auth.credentials.admin) {
14
+ if (!auth.credentials.moderator) {
15
15
  throw new AuthRequiredError('Insufficient privileges')
16
16
  }
17
17
  const { account } = input.body
@@ -16,6 +16,7 @@ export default function (server: Server, ctx: AppContext) {
16
16
  recipientDid,
17
17
  senderDid,
18
18
  subject = 'Message from Bluesky moderator',
19
+ comment,
19
20
  } = input.body
20
21
  const account = await ctx.accountManager.getAccount(recipientDid)
21
22
  if (!account) {
@@ -44,6 +45,7 @@ export default function (server: Server, ctx: AppContext) {
44
45
  event: {
45
46
  $type: 'com.atproto.admin.defs#modEventEmail',
46
47
  subjectLine: subject,
48
+ comment,
47
49
  },
48
50
  subject: {
49
51
  $type: 'com.atproto.admin.defs#repoRef',
@@ -10,6 +10,7 @@ import {
10
10
  REASONRUDE,
11
11
  REASONSEXUAL,
12
12
  REASONVIOLATION,
13
+ REASONAPPEAL,
13
14
  } from '../../../../lexicon/types/com/atproto/moderation/defs'
14
15
  import { parseCidParam } from '../../../../util/params'
15
16
 
@@ -49,4 +50,5 @@ const reasonTypes = new Set([
49
50
  REASONRUDE,
50
51
  REASONSEXUAL,
51
52
  REASONVIOLATION,
53
+ REASONAPPEAL,
52
54
  ])
@@ -2,12 +2,12 @@ import { DidDocument, MINUTE, check } from '@atproto/common'
2
2
  import { AtprotoData, ensureAtpDocument } from '@atproto/identity'
3
3
  import { InvalidRequestError } from '@atproto/xrpc-server'
4
4
  import { ExportableKeypair, Keypair, Secp256k1Keypair } from '@atproto/crypto'
5
+ import * as plc from '@did-plc/lib'
5
6
  import disposable from 'disposable-email'
6
7
  import {
7
8
  baseNormalizeAndValidate,
8
9
  normalizeAndValidateHandle,
9
10
  } from '../../../../handle'
10
- import * as plc from '@did-plc/lib'
11
11
  import { Server } from '../../../../lexicon'
12
12
  import { InputSchema as CreateAccountInput } from '../../../../lexicon/types/com/atproto/server/createAccount'
13
13
  import AppContext from '../../../../context'
@@ -101,7 +101,12 @@ const validateInputsForEntrywayPds = async (
101
101
  'IncompatibleDidDoc',
102
102
  )
103
103
  }
104
- await plc.assureValidOp(plcOp)
104
+ try {
105
+ await plc.assureValidOp(plcOp)
106
+ await plc.assureValidSig([plcRotationKey], plcOp)
107
+ } catch (err) {
108
+ throw new InvalidRequestError('invalid plc operation', 'IncompatibleDidDoc')
109
+ }
105
110
  const doc = plc.formatDidDoc({ did, ...plcOp })
106
111
  const data = ensureAtpDocument(doc)
107
112
 
@@ -135,6 +135,7 @@ export const COM_ATPROTO_MODERATION = {
135
135
  DefsReasonSexual: 'com.atproto.moderation.defs#reasonSexual',
136
136
  DefsReasonRude: 'com.atproto.moderation.defs#reasonRude',
137
137
  DefsReasonOther: 'com.atproto.moderation.defs#reasonOther',
138
+ DefsReasonAppeal: 'com.atproto.moderation.defs#reasonAppeal',
138
139
  }
139
140
  export const APP_BSKY_GRAPH = {
140
141
  DefsModlist: 'app.bsky.graph.defs#modlist',
@@ -102,6 +102,7 @@ export const schemaDict = {
102
102
  'lex:com.atproto.admin.defs#modEventAcknowledge',
103
103
  'lex:com.atproto.admin.defs#modEventEscalate',
104
104
  'lex:com.atproto.admin.defs#modEventMute',
105
+ 'lex:com.atproto.admin.defs#modEventResolveAppeal',
105
106
  ],
106
107
  },
107
108
  subject: {
@@ -237,9 +238,20 @@ export const schemaDict = {
237
238
  type: 'string',
238
239
  format: 'datetime',
239
240
  },
241
+ lastAppealedAt: {
242
+ type: 'string',
243
+ format: 'datetime',
244
+ description:
245
+ 'Timestamp referencing when the author of the subject appealed a moderation action',
246
+ },
240
247
  takendown: {
241
248
  type: 'boolean',
242
249
  },
250
+ appealed: {
251
+ type: 'boolean',
252
+ description:
253
+ 'True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators.',
254
+ },
243
255
  suspendUntil: {
244
256
  type: 'string',
245
257
  format: 'datetime',
@@ -717,6 +729,16 @@ export const schemaDict = {
717
729
  },
718
730
  },
719
731
  },
732
+ modEventResolveAppeal: {
733
+ type: 'object',
734
+ description: 'Resolve appeal on a subject',
735
+ properties: {
736
+ comment: {
737
+ type: 'string',
738
+ description: 'Describe resolution.',
739
+ },
740
+ },
741
+ },
720
742
  modEventComment: {
721
743
  type: 'object',
722
744
  description: 'Add a comment to a subject',
@@ -816,6 +838,10 @@ export const schemaDict = {
816
838
  type: 'string',
817
839
  description: 'The subject line of the email sent to the user.',
818
840
  },
841
+ comment: {
842
+ type: 'string',
843
+ description: 'Additional comment about the outgoing comm.',
844
+ },
819
845
  },
820
846
  },
821
847
  },
@@ -1357,6 +1383,10 @@ export const schemaDict = {
1357
1383
  type: 'boolean',
1358
1384
  description: 'Get subjects that were taken down',
1359
1385
  },
1386
+ appealed: {
1387
+ type: 'boolean',
1388
+ description: 'Get subjects in unresolved appealed status',
1389
+ },
1360
1390
  limit: {
1361
1391
  type: 'integer',
1362
1392
  minimum: 1,
@@ -1467,6 +1497,11 @@ export const schemaDict = {
1467
1497
  type: 'string',
1468
1498
  format: 'did',
1469
1499
  },
1500
+ comment: {
1501
+ type: 'string',
1502
+ description:
1503
+ "Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers",
1504
+ },
1470
1505
  },
1471
1506
  },
1472
1507
  },
@@ -1937,6 +1972,7 @@ export const schemaDict = {
1937
1972
  'com.atproto.moderation.defs#reasonSexual',
1938
1973
  'com.atproto.moderation.defs#reasonRude',
1939
1974
  'com.atproto.moderation.defs#reasonOther',
1975
+ 'com.atproto.moderation.defs#reasonAppeal',
1940
1976
  ],
1941
1977
  },
1942
1978
  reasonSpam: {
@@ -1964,6 +2000,10 @@ export const schemaDict = {
1964
2000
  type: 'token',
1965
2001
  description: 'Other: reports not falling under another report category',
1966
2002
  },
2003
+ reasonAppeal: {
2004
+ type: 'token',
2005
+ description: 'Appeal: appeal a previously taken moderation action',
2006
+ },
1967
2007
  },
1968
2008
  },
1969
2009
  ComAtprotoRepoApplyWrites: {
@@ -76,6 +76,7 @@ export interface ModEventViewDetail {
76
76
  | ModEventAcknowledge
77
77
  | ModEventEscalate
78
78
  | ModEventMute
79
+ | ModEventResolveAppeal
79
80
  | { $type: string; [k: string]: unknown }
80
81
  subject:
81
82
  | RepoView
@@ -147,7 +148,11 @@ export interface SubjectStatusView {
147
148
  lastReviewedBy?: string
148
149
  lastReviewedAt?: string
149
150
  lastReportedAt?: string
151
+ /** Timestamp referencing when the author of the subject appealed a moderation action */
152
+ lastAppealedAt?: string
150
153
  takendown?: boolean
154
+ /** True indicates that the a previously taken moderator action was appealed against, by the author of the content. False indicates last appeal was resolved by moderators. */
155
+ appealed?: boolean
151
156
  suspendUntil?: string
152
157
  [k: string]: unknown
153
158
  }
@@ -538,6 +543,27 @@ export function validateModEventReverseTakedown(v: unknown): ValidationResult {
538
543
  return lexicons.validate('com.atproto.admin.defs#modEventReverseTakedown', v)
539
544
  }
540
545
 
546
+ /** Resolve appeal on a subject */
547
+ export interface ModEventResolveAppeal {
548
+ /** Describe resolution. */
549
+ comment?: string
550
+ [k: string]: unknown
551
+ }
552
+
553
+ export function isModEventResolveAppeal(
554
+ v: unknown,
555
+ ): v is ModEventResolveAppeal {
556
+ return (
557
+ isObj(v) &&
558
+ hasProp(v, '$type') &&
559
+ v.$type === 'com.atproto.admin.defs#modEventResolveAppeal'
560
+ )
561
+ }
562
+
563
+ export function validateModEventResolveAppeal(v: unknown): ValidationResult {
564
+ return lexicons.validate('com.atproto.admin.defs#modEventResolveAppeal', v)
565
+ }
566
+
541
567
  /** Add a comment to a subject */
542
568
  export interface ModEventComment {
543
569
  comment: string
@@ -674,6 +700,8 @@ export function validateModEventUnmute(v: unknown): ValidationResult {
674
700
  export interface ModEventEmail {
675
701
  /** The subject line of the email sent to the user. */
676
702
  subjectLine: string
703
+ /** Additional comment about the outgoing comm. */
704
+ comment?: string
677
705
  [k: string]: unknown
678
706
  }
679
707
 
@@ -32,6 +32,8 @@ export interface QueryParams {
32
32
  sortDirection: 'asc' | 'desc'
33
33
  /** Get subjects that were taken down */
34
34
  takendown?: boolean
35
+ /** Get subjects in unresolved appealed status */
36
+ appealed?: boolean
35
37
  limit: number
36
38
  cursor?: string
37
39
  }
@@ -15,6 +15,8 @@ export interface InputSchema {
15
15
  content: string
16
16
  subject?: string
17
17
  senderDid: string
18
+ /** Additional comment by the sender that won't be used in the email itself but helpful to provide more context for moderators/reviewers */
19
+ comment?: string
18
20
  [k: string]: unknown
19
21
  }
20
22
 
@@ -13,6 +13,7 @@ export type ReasonType =
13
13
  | 'com.atproto.moderation.defs#reasonSexual'
14
14
  | 'com.atproto.moderation.defs#reasonRude'
15
15
  | 'com.atproto.moderation.defs#reasonOther'
16
+ | 'com.atproto.moderation.defs#reasonAppeal'
16
17
  | (string & {})
17
18
 
18
19
  /** Spam: frequent unwanted promotion, replies, mentions */
@@ -27,3 +28,5 @@ export const REASONSEXUAL = 'com.atproto.moderation.defs#reasonSexual'
27
28
  export const REASONRUDE = 'com.atproto.moderation.defs#reasonRude'
28
29
  /** Other: reports not falling under another report category */
29
30
  export const REASONOTHER = 'com.atproto.moderation.defs#reasonOther'
31
+ /** Appeal: appeal a previously taken moderation action */
32
+ export const REASONAPPEAL = 'com.atproto.moderation.defs#reasonAppeal'
@@ -1,5 +1,6 @@
1
1
  import * as os from 'node:os'
2
2
  import * as path from 'node:path'
3
+ import * as plcLib from '@did-plc/lib'
3
4
  import AtpAgent from '@atproto/api'
4
5
  import { Secp256k1Keypair, randomStr } from '@atproto/crypto'
5
6
  import { SeedClient, TestPds, TestPlc, mockResolvers } from '@atproto/dev-env'
@@ -131,6 +132,28 @@ describe('entryway', () => {
131
132
  expect(accountFromPds?.handle).toEqual('alice3.test')
132
133
  expect(accountFromEntryway?.handle).toEqual('alice3.test')
133
134
  })
135
+
136
+ it('does not allow bringing own op to account creation.', async () => {
137
+ const {
138
+ data: { signingKey },
139
+ } = await pdsAgent.api.com.atproto.server.reserveSigningKey({})
140
+ const rotationKey = await Secp256k1Keypair.create()
141
+ const plcCreate = await plcLib.createOp({
142
+ signingKey,
143
+ rotationKeys: [rotationKey.did(), entryway.ctx.plcRotationKey.did()],
144
+ handle: 'weirdalice.test',
145
+ pds: pds.ctx.cfg.service.publicUrl,
146
+ signer: rotationKey,
147
+ })
148
+ const tryCreateAccount = pdsAgent.api.com.atproto.server.createAccount(
149
+ { did: plcCreate.did, plcOp: plcCreate.op, handle: 'weirdalice.test' },
150
+ {
151
+ headers: SeedClient.getHeaders(accessToken),
152
+ encoding: 'application/json',
153
+ },
154
+ )
155
+ await expect(tryCreateAccount).rejects.toThrow('invalid plc operation')
156
+ })
134
157
  })
135
158
 
136
159
  const createEntryway = async (
@@ -177,13 +177,13 @@ describe('pds admin invite views', () => {
177
177
  expect(aliceView.data.invites?.length).toBe(6)
178
178
  })
179
179
 
180
- it('does not allow non-admin moderators to disable invites.', async () => {
180
+ it('does not allow triage moderators to disable invites.', async () => {
181
181
  const attemptDisableInvites =
182
182
  agent.api.com.atproto.admin.disableInviteCodes(
183
183
  { codes: ['x'], accounts: [alice] },
184
184
  {
185
185
  encoding: 'application/json',
186
- headers: network.pds.adminAuthHeaders('moderator'),
186
+ headers: network.pds.adminAuthHeaders('triage'),
187
187
  },
188
188
  )
189
189
  await expect(attemptDisableInvites).rejects.toThrow(
@@ -255,12 +255,12 @@ describe('pds admin invite views', () => {
255
255
  expect(res.every((row) => row.disabled === 1))
256
256
  })
257
257
 
258
- it('does not allow non-admin moderations to disable account invites', async () => {
258
+ it('does not allow triage moderators to disable account invites', async () => {
259
259
  const attempt = agent.api.com.atproto.admin.disableAccountInvites(
260
260
  { account: alice },
261
261
  {
262
262
  encoding: 'application/json',
263
- headers: network.pds.adminAuthHeaders('moderator'),
263
+ headers: network.pds.adminAuthHeaders('triage'),
264
264
  },
265
265
  )
266
266
  await expect(attempt).rejects.toThrow('Insufficient privileges')
@@ -285,12 +285,12 @@ describe('pds admin invite views', () => {
285
285
  expect(invRes.data.codes.length).toBeGreaterThan(0)
286
286
  })
287
287
 
288
- it('does not allow non-admin moderations to enable account invites', async () => {
288
+ it('does not allow triage moderators to enable account invites', async () => {
289
289
  const attempt = agent.api.com.atproto.admin.enableAccountInvites(
290
290
  { account: alice },
291
291
  {
292
292
  encoding: 'application/json',
293
- headers: network.pds.adminAuthHeaders('moderator'),
293
+ headers: network.pds.adminAuthHeaders('triage'),
294
294
  },
295
295
  )
296
296
  await expect(attempt).rejects.toThrow('Insufficient privileges')