@evanp/activitypub-bot 0.38.2 → 0.38.3

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.
@@ -130,43 +130,43 @@ export class ActivityDeliverer {
130
130
  const recipients = this.getRecipients(activity)
131
131
 
132
132
  for (const recipient of recipients) {
133
- this.#logger.debug(`Checking recipient ${recipient.id}`)
133
+ this.#logger.debug({ recipient: recipient.id }, 'Checking recipient')
134
134
  if (this.#isPublic(recipient)) {
135
- this.#logger.debug(`Public recipient for ${activity.id}`)
135
+ this.#logger.debug({ activity: activity.id }, 'Public recipient')
136
136
  await this.deliverPublic(activity, bots)
137
137
  } else if (this.#isLocal(recipient)) {
138
- this.#logger.debug(`Local recipient for ${activity.id}`)
138
+ this.#logger.debug({ activity: activity.id }, 'Local recipient')
139
139
  const parts = this.#formatter.unformat(recipient.id)
140
140
  if (this.#isLocalActor(parts)) {
141
- this.#logger.debug(`Local actor ${recipient.id} for ${activity.id}`)
141
+ this.#logger.debug({ recipient: recipient.id, activity: activity.id }, 'Local actor recipient')
142
142
  await this.#deliverLocalActor(activity, recipient, bots, deliveredTo)
143
143
  } else if (this.#isLocalFollowersCollection(parts)) {
144
- this.#logger.debug(`Local followers for ${parts.username} for ${activity.id}`)
144
+ this.#logger.debug({ username: parts.username, activity: activity.id }, 'Local followers recipient')
145
145
  await this.#deliverLocalFollowersCollection(activity, parts.username, bots, deliveredTo)
146
146
  } else if (this.#isLocalFollowingCollection(parts)) {
147
- this.#logger.debug(`Local following for ${parts.username} for ${activity.id}`)
147
+ this.#logger.debug({ username: parts.username, activity: activity.id }, 'Local following recipient')
148
148
  await this.#deliverLocalFollowingCollection(activity, parts.username, bots, deliveredTo)
149
149
  } else {
150
150
  this.#logger.warn(
151
- `Unrecognized recipient for remote delivery: ${recipient.id}`
151
+ { recipient: recipient.id }, 'Unrecognized recipient for remote delivery'
152
152
  )
153
153
  }
154
154
  } else {
155
155
  const fullActor = await this.#client.get(actor.id)
156
156
  const fullRecipient = await this.#client.get(recipient.id)
157
157
  if (await this.#isRemoteActor(fullRecipient)) {
158
- this.#logger.warn(`Skipping remote actor ${recipient.id}`)
158
+ this.#logger.warn({ recipient: recipient.id }, 'Skipping remote actor')
159
159
  } else if (await this.#isRemoteFollowersCollection(fullActor, fullRecipient)) {
160
- this.#logger.debug(`Remote followers for ${fullActor.id} for ${activity.id}`)
160
+ this.#logger.debug({ actor: fullActor.id, activity: activity.id }, 'Remote followers recipient')
161
161
  await this.#deliverRemoteFollowersCollection(activity, fullRecipient, fullActor, deliveredTo, bots)
162
162
  } else if (await this.#isRemoteFollowingCollection(fullActor, fullRecipient)) {
163
- this.#logger.debug(`Remote following for ${fullActor.id} for ${activity.id}`)
163
+ this.#logger.debug({ actor: fullActor.id, activity: activity.id }, 'Remote following recipient')
164
164
  await this.#deliverRemoteFollowingCollection(activity, fullRecipient, fullActor, deliveredTo, bots)
165
165
  } else if (await this.#isRemoteCollection(fullRecipient)) {
166
- this.#logger.debug(`Remote collection ${fullRecipient.id} for ${activity.id}`)
166
+ this.#logger.debug({ recipient: fullRecipient.id, activity: activity.id }, 'Remote collection recipient')
167
167
  await this.#deliverRemoteCollection(activity, fullRecipient, deliveredTo, bots)
168
168
  } else {
169
- this.#logger.warn(`Unrecognized recipient: ${recipient.id}`)
169
+ this.#logger.warn({ recipient: recipient.id }, 'Unrecognized recipient')
170
170
  }
171
171
  }
172
172
  }
@@ -217,7 +217,7 @@ export class ActivityDeliverer {
217
217
  if (!deliveredTo.has(username)) {
218
218
  const bot = await BotMaker.makeBot(bots, username)
219
219
  if (!bot) {
220
- this.#logger.warn(`sharedInbox direct delivery for unknown bot ${username}`)
220
+ this.#logger.warn({ username }, 'sharedInbox direct delivery for unknown bot')
221
221
  }
222
222
  await this.deliverTo(activity, bot)
223
223
  deliveredTo.add(username)
@@ -230,7 +230,7 @@ export class ActivityDeliverer {
230
230
  if (!deliveredTo.has(username)) {
231
231
  const bot = await BotMaker.makeBot(bots, username)
232
232
  if (!bot) {
233
- this.#logger.warn(`sharedInbox direct delivery for unknown bot ${username}`)
233
+ this.#logger.warn({ username }, 'sharedInbox direct delivery for unknown bot')
234
234
  continue
235
235
  }
236
236
  await this.deliverTo(activity, bot)
@@ -245,7 +245,7 @@ export class ActivityDeliverer {
245
245
  if (!deliveredTo.has(username)) {
246
246
  const bot = await BotMaker.makeBot(bots, username)
247
247
  if (!bot) {
248
- this.#logger.warn(`sharedInbox direct delivery for unknown bot ${username}`)
248
+ this.#logger.warn({ username }, 'sharedInbox direct delivery for unknown bot')
249
249
  continue
250
250
  }
251
251
  await this.deliverTo(activity, bot)
@@ -298,7 +298,7 @@ export class ActivityDeliverer {
298
298
  if (!deliveredTo.has(follower)) {
299
299
  const bot = await BotMaker.makeBot(bots, follower)
300
300
  if (!bot) {
301
- this.#logger.warn(`sharedInbox delivery for unknown bot ${follower}`)
301
+ this.#logger.warn({ username: follower }, 'sharedInbox delivery for unknown bot')
302
302
  continue
303
303
  }
304
304
  await this.deliverTo(activity, bot)
@@ -315,7 +315,7 @@ export class ActivityDeliverer {
315
315
  if (!deliveredTo.has(followed)) {
316
316
  const bot = await BotMaker.makeBot(bots, followed)
317
317
  if (!bot) {
318
- this.#logger.warn(`sharedInbox delivery for unknown bot ${followed}`)
318
+ this.#logger.warn({ username: followed }, 'sharedInbox delivery for unknown bot')
319
319
  continue
320
320
  }
321
321
  await this.deliverTo(activity, bot)
@@ -326,13 +326,13 @@ export class ActivityDeliverer {
326
326
 
327
327
  async #deliverRemoteCollection (activity, recipient, deliveredTo, bots) {
328
328
  for await (const item of this.#client.items(recipient.id)) {
329
- this.#logger.debug(`item: ${JSON.stringify(item)}`)
329
+ this.#logger.debug({ item: item.id }, 'Remote collection item')
330
330
  if (this.#isLocal(item)) {
331
331
  const parts = this.#formatter.unformat(item.id)
332
332
  if (this.#isLocalActor(parts)) {
333
333
  const bot = await BotMaker.makeBot(bots, parts.username)
334
334
  if (!bot) {
335
- this.#logger.warn(`sharedInbox delivery for unknown bot ${parts.username}`)
335
+ this.#logger.warn({ username: parts.username }, 'sharedInbox delivery for unknown bot')
336
336
  continue
337
337
  }
338
338
  await this.deliverTo(activity, bot)
@@ -74,7 +74,7 @@ export class ActivityHandler {
74
74
  case AS2 + 'Block': await this.#handleBlock(bot, activity); break
75
75
  case AS2 + 'Flag': await this.#handleFlag(bot, activity); break
76
76
  default:
77
- this.#logger.warn(`Unhandled activity type: ${activity.type}`)
77
+ this.#logger.warn({ type: activity.type }, 'Unhandled activity type')
78
78
  }
79
79
  }
80
80
 
@@ -655,7 +655,7 @@ export class ActivityHandler {
655
655
  async #handleFlag (bot, activity) {
656
656
  const actor = this.#getActor(activity)
657
657
  const object = this.#getObject(activity)
658
- this.#logger.warn(`Actor ${actor.id} flagged object ${object.id} for review.`)
658
+ this.#logger.warn({ actor: actor.id, object: object.id }, 'Actor flagged object for review')
659
659
  }
660
660
 
661
661
  async #handleUndo (bot, undoActivity) {
@@ -128,7 +128,7 @@ export class ActivityPubClient {
128
128
  }
129
129
  this.#logger.debug({ headers }, 'Sending headers')
130
130
  const method = 'GET'
131
- this.#logger.debug(`Signing GET request for ${baseUrl}`)
131
+ this.#logger.debug({ url: baseUrl }, 'Signing GET request')
132
132
  if (sign) {
133
133
  headers.signature =
134
134
  await this.#sign({ username, url: baseUrl, method, headers })
@@ -136,7 +136,7 @@ export class ActivityPubClient {
136
136
  const hostname = parsed.hostname
137
137
  this.#logger.debug({ url: baseUrl, hostname }, 'Waiting for rate limiter')
138
138
  await this.#limiter.limit(hostname)
139
- this.#logger.debug(`Fetching ${baseUrl} with GET`)
139
+ this.#logger.debug({ url: baseUrl }, 'Fetching with GET')
140
140
  const res = await fetch(baseUrl,
141
141
  {
142
142
  method,
@@ -145,7 +145,7 @@ export class ActivityPubClient {
145
145
  )
146
146
  this.#logger.debug({ hostname, status: res.status }, 'response received')
147
147
  await this.#limiter.update(hostname, res.headers)
148
- this.#logger.debug(`Finished getting ${url}`)
148
+ this.#logger.debug({ url }, 'Finished GET')
149
149
  if (useCache && res.status === 304) {
150
150
  this.#logger.debug({ baseUrl }, '304 Not Modified, returning cached object')
151
151
  return cached.object
@@ -217,12 +217,12 @@ export class ActivityPubClient {
217
217
  }
218
218
  const method = 'POST'
219
219
  assert.ok(headers)
220
- this.#logger.debug(`Signing POST for ${url}`)
220
+ this.#logger.debug({ url }, 'Signing POST')
221
221
  headers.signature = await this.#sign({ username, url, method, headers })
222
222
  const hostname = (new URL(url)).hostname
223
223
  this.#logger.debug({ url, hostname }, 'Waiting for rate limiter')
224
224
  await this.#limiter.limit(hostname)
225
- this.#logger.debug(`Fetching POST for ${url}`)
225
+ this.#logger.debug({ url }, 'Fetching POST')
226
226
  const res = await fetch(url,
227
227
  {
228
228
  method,
@@ -232,7 +232,7 @@ export class ActivityPubClient {
232
232
  )
233
233
  this.#logger.debug({ hostname }, 'updating limiter')
234
234
  await this.#limiter.update(hostname, res.headers)
235
- this.#logger.debug(`Done fetching POST for ${url}`)
235
+ this.#logger.debug({ url }, 'Done fetching POST')
236
236
  if (res.status < 200 || res.status > 299) {
237
237
  throw createHttpError(
238
238
  res.status,
@@ -267,7 +267,7 @@ export class ActivityPubClient {
267
267
 
268
268
  const coll = await this.get(id, username)
269
269
 
270
- this.#logger.debug(`Got object ${id}`)
270
+ this.#logger.debug({ id }, 'Got object')
271
271
 
272
272
  if (!this.#isCollection(coll)) {
273
273
  throw new Error(`Can only iterate over a collection: ${id}`)
@@ -277,17 +277,17 @@ export class ActivityPubClient {
277
277
 
278
278
  if (items) {
279
279
  for (const item of items) {
280
- this.#logger.debug(`Yielding ${item.id}`)
280
+ this.#logger.debug({ id: item.id }, 'Yielding item')
281
281
  yield item
282
282
  }
283
283
  } else if (coll.first) {
284
284
  for (let page = coll.first; page; page = page.next) {
285
- this.#logger.debug(`Getting page ${page.id}`)
285
+ this.#logger.debug({ id: page.id }, 'Getting page')
286
286
  page = await this.get(page.id)
287
287
  const items = (page.items) ? page.items : page.orderedItems
288
288
  if (items) {
289
289
  for (const item of items) {
290
- this.#logger.debug(`Yielding ${item.id}`)
290
+ this.#logger.debug({ id: item.id }, 'Yielding item')
291
291
  yield item
292
292
  }
293
293
  }
@@ -89,6 +89,208 @@ as2.registerContext('https://w3id.org/security/v1', {
89
89
  }
90
90
  })
91
91
 
92
+ as2.registerContext('https://w3id.org/security/data-integrity/v1', {
93
+ '@context': {
94
+ id: '@id',
95
+ type: '@type',
96
+ '@protected': true,
97
+ proof: {
98
+ '@id': 'https://w3id.org/security#proof',
99
+ '@type': '@id',
100
+ '@container': '@graph'
101
+ },
102
+ DataIntegrityProof: {
103
+ '@id': 'https://w3id.org/security#DataIntegrityProof',
104
+ '@context': {
105
+ '@protected': true,
106
+ id: '@id',
107
+ type: '@type',
108
+ challenge: 'https://w3id.org/security#challenge',
109
+ created: {
110
+ '@id': 'http://purl.org/dc/terms/created',
111
+ '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
112
+ },
113
+ domain: 'https://w3id.org/security#domain',
114
+ expires: {
115
+ '@id': 'https://w3id.org/security#expiration',
116
+ '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
117
+ },
118
+ nonce: 'https://w3id.org/security#nonce',
119
+ proofPurpose: {
120
+ '@id': 'https://w3id.org/security#proofPurpose',
121
+ '@type': '@vocab',
122
+ '@context': {
123
+ '@protected': true,
124
+ id: '@id',
125
+ type: '@type',
126
+ assertionMethod: {
127
+ '@id': 'https://w3id.org/security#assertionMethod',
128
+ '@type': '@id',
129
+ '@container': '@set'
130
+ },
131
+ authentication: {
132
+ '@id': 'https://w3id.org/security#authenticationMethod',
133
+ '@type': '@id',
134
+ '@container': '@set'
135
+ },
136
+ capabilityInvocation: {
137
+ '@id': 'https://w3id.org/security#capabilityInvocationMethod',
138
+ '@type': '@id',
139
+ '@container': '@set'
140
+ },
141
+ capabilityDelegation: {
142
+ '@id': 'https://w3id.org/security#capabilityDelegationMethod',
143
+ '@type': '@id',
144
+ '@container': '@set'
145
+ },
146
+ keyAgreement: {
147
+ '@id': 'https://w3id.org/security#keyAgreementMethod',
148
+ '@type': '@id',
149
+ '@container': '@set'
150
+ }
151
+ }
152
+ },
153
+ cryptosuite: 'https://w3id.org/security#cryptosuite',
154
+ proofValue: {
155
+ '@id': 'https://w3id.org/security#proofValue',
156
+ '@type': 'https://w3id.org/security#multibase'
157
+ },
158
+ verificationMethod: {
159
+ '@id': 'https://w3id.org/security#verificationMethod',
160
+ '@type': '@id'
161
+ }
162
+ }
163
+ }
164
+ }
165
+ })
166
+
167
+ as2.registerContext('https://www.w3.org/ns/did/v1', {
168
+ '@context': {
169
+ '@protected': true,
170
+ id: '@id',
171
+ type: '@type',
172
+ alsoKnownAs: {
173
+ '@id': 'https://www.w3.org/ns/activitystreams#alsoKnownAs',
174
+ '@type': '@id'
175
+ },
176
+ assertionMethod: {
177
+ '@id': 'https://w3id.org/security#assertionMethod',
178
+ '@type': '@id',
179
+ '@container': '@set'
180
+ },
181
+ authentication: {
182
+ '@id': 'https://w3id.org/security#authenticationMethod',
183
+ '@type': '@id',
184
+ '@container': '@set'
185
+ },
186
+ capabilityDelegation: {
187
+ '@id': 'https://w3id.org/security#capabilityDelegationMethod',
188
+ '@type': '@id',
189
+ '@container': '@set'
190
+ },
191
+ capabilityInvocation: {
192
+ '@id': 'https://w3id.org/security#capabilityInvocationMethod',
193
+ '@type': '@id',
194
+ '@container': '@set'
195
+ },
196
+ controller: {
197
+ '@id': 'https://w3id.org/security#controller',
198
+ '@type': '@id'
199
+ },
200
+ keyAgreement: {
201
+ '@id': 'https://w3id.org/security#keyAgreementMethod',
202
+ '@type': '@id',
203
+ '@container': '@set'
204
+ },
205
+ service: {
206
+ '@id': 'https://www.w3.org/ns/did#service',
207
+ '@type': '@id',
208
+ '@context': {
209
+ '@protected': true,
210
+ id: '@id',
211
+ type: '@type',
212
+ serviceEndpoint: {
213
+ '@id': 'https://www.w3.org/ns/did#serviceEndpoint',
214
+ '@type': '@id'
215
+ }
216
+ }
217
+ },
218
+ verificationMethod: {
219
+ '@id': 'https://w3id.org/security#verificationMethod',
220
+ '@type': '@id'
221
+ }
222
+ }
223
+ })
224
+
225
+ as2.registerContext('https://w3id.org/security/multikey/v1', {
226
+ '@context': {
227
+ id: '@id',
228
+ type: '@type',
229
+ '@protected': true,
230
+ Multikey: {
231
+ '@id': 'https://w3id.org/security#Multikey',
232
+ '@context': {
233
+ '@protected': true,
234
+ id: '@id',
235
+ type: '@type',
236
+ controller: {
237
+ '@id': 'https://w3id.org/security#controller',
238
+ '@type': '@id'
239
+ },
240
+ revoked: {
241
+ '@id': 'https://w3id.org/security#revoked',
242
+ '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
243
+ },
244
+ expires: {
245
+ '@id': 'https://w3id.org/security#expiration',
246
+ '@type': 'http://www.w3.org/2001/XMLSchema#dateTime'
247
+ },
248
+ publicKeyMultibase: {
249
+ '@id': 'https://w3id.org/security#publicKeyMultibase',
250
+ '@type': 'https://w3id.org/security#multibase'
251
+ },
252
+ secretKeyMultibase: {
253
+ '@id': 'https://w3id.org/security#secretKeyMultibase',
254
+ '@type': 'https://w3id.org/security#multibase'
255
+ }
256
+ }
257
+ }
258
+ }
259
+ })
260
+
261
+ as2.registerContext('https://gotosocial.org/ns', {
262
+ '@context': {
263
+ xsd: 'http://www.w3.org/2001/XMLSchema#',
264
+ gts: 'https://gotosocial.org/ns#',
265
+ LikeRequest: 'gts:LikeRequest',
266
+ ReplyRequest: 'gts:ReplyRequest',
267
+ AnnounceRequest: 'gts:AnnounceRequest',
268
+ QuoteRequest: 'gts:QuoteRequest',
269
+ LikeAuthorization: 'gts:LikeApproval',
270
+ ReplyAuthorization: 'gts:ReplyAuthorization',
271
+ AnnounceAuthorization: 'gts:AnnounceAuthorization',
272
+ QuoteAuthorization: 'gts:QuoteAuthorization',
273
+ likeAuthorization: { '@id': 'gts:likeAuthorization', '@type': '@id' },
274
+ replyAuthorization: { '@id': 'gts:replyAuthorization', '@type': '@id' },
275
+ announceAuthorization: { '@id': 'gts:announceAuthorization', '@type': '@id' },
276
+ quoteAuthorization: { '@id': 'gts:quoteAuthorization', '@type': '@id' },
277
+ interactingObject: { '@id': 'gts:interactingObject', '@type': '@id' },
278
+ interactionTarget: { '@id': 'gts:interactionTarget', '@type': '@id' },
279
+ interactionPolicy: { '@id': 'gts:interactionPolicy', '@type': '@id' },
280
+ canLike: { '@id': 'gts:canLike', '@type': '@id' },
281
+ canReply: { '@id': 'gts:canReply', '@type': '@id' },
282
+ canAnnounce: { '@id': 'gts:canAnnounce', '@type': '@id' },
283
+ canQuote: { '@id': 'gts:canQuote', '@type': '@id' },
284
+ automaticApproval: { '@id': 'gts:automaticApproval', '@type': '@id' },
285
+ manualApproval: { '@id': 'gts:manualApproval', '@type': '@id' },
286
+ hidesToPublicFromUnauthedWeb: { '@id': 'gts:hidesToPublicFromUnauthedWeb', '@type': 'xsd:boolean' },
287
+ hidesCcPublicFromUnauthedWeb: { '@id': 'gts:hidesCcPublicFromUnauthedWeb', '@type': 'xsd:boolean' },
288
+ always: { '@id': 'gts:always', '@type': '@id' },
289
+ approvalRequired: { '@id': 'gts:approvalRequired', '@type': '@id' },
290
+ approvedBy: { '@id': 'gts:approvedBy', '@type': '@id' }
291
+ }
292
+ })
293
+
92
294
  as2.registerContext('https://purl.archive.org/socialweb/thread/1.0', {
93
295
  '@context': {
94
296
  thr: 'https://purl.archive.org/socialweb/thread#',
@@ -54,8 +54,8 @@ export class DeliveryWorker extends Worker {
54
54
  'handler failed for activity'
55
55
  )
56
56
  }
57
- this._logger.debug(`Adding ${activity.id} to ${bot.username} inbox`)
57
+ this._logger.debug({ activity: activity.id, bot: bot.username }, 'Adding to inbox')
58
58
  await this.#actorStorage.addToCollection(bot.username, 'inbox', activity)
59
- this._logger.debug(`Done adding ${activity.id} to ${bot.username} inbox`)
59
+ this._logger.debug({ activity: activity.id, bot: bot.username }, 'Done adding to inbox')
60
60
  }
61
61
  }
@@ -18,7 +18,7 @@ export class DistributionWorker extends Worker {
18
18
  const activityObj = await as2.import(activity)
19
19
  try {
20
20
  await this.#client.post(inbox, activityObj, username)
21
- this._logger.info(`Delivered ${activity.id} to ${inbox}`)
21
+ this._logger.info({ activity: activity.id, inbox }, 'Delivered activity')
22
22
  } catch (error) {
23
23
  if (!error.status) {
24
24
  this._logger.warn(
@@ -46,15 +46,15 @@ export class HTTPSignatureAuthenticator {
46
46
  parts = formatter.unformat(fullUrl)
47
47
  } catch (err) {
48
48
  // do nothing
49
- this.#logger.debug({ fullUrl, err }, 'Could not unformat')
49
+ this.#logger.debug({ reqId: req.id, fullUrl, err }, 'Could not unformat')
50
50
  }
51
51
  if (parts && parts.username) {
52
- this.#logger.debug({ username: parts.username }, 'Request for bot')
52
+ this.#logger.debug({ reqId: req.id, username: parts.username }, 'Request for bot')
53
53
  const bot = await BotMaker.makeBot(bots, parts.username)
54
54
  if (!bot) {
55
- this.#logger.warn({ username: parts.username }, 'no such bot')
55
+ this.#logger.warn({ reqId: req.id, username: parts.username }, 'no such bot')
56
56
  } else if (!bot.checkSignature) {
57
- this.#logger.debug({ username: parts.username }, 'bot says no sig')
57
+ this.#logger.debug({ reqId: req.id, username: parts.username }, 'bot says no sig')
58
58
  return next()
59
59
  }
60
60
  }
@@ -68,13 +68,13 @@ export class HTTPSignatureAuthenticator {
68
68
  await this.#authenticateSignature(signature, originalUrl, req, res, next)
69
69
  }
70
70
  } catch (err) {
71
- this.#logger.debug({ err }, 'Error authenticating key')
71
+ this.#logger.debug({ reqId: req.id, err }, 'Error authenticating key')
72
72
  return next(err)
73
73
  }
74
74
  }
75
75
 
76
76
  async #authenticateSignature (signature, originalUrl, req, res, next) {
77
- this.#logger.debug({ signature }, 'Got signed request')
77
+ this.#logger.debug({ reqId: req.id, signature }, 'Got signed request')
78
78
  const date = req.get('Date')
79
79
  if (!date) {
80
80
  throw createHttpError(400, 'No date provided')
@@ -90,14 +90,14 @@ export class HTTPSignatureAuthenticator {
90
90
  }
91
91
  const calculated = await this.#digester.digest(req.rawBodyText)
92
92
  if (!this.#digester.equals(digest, calculated)) {
93
- this.#logger.debug(`calculated: ${calculated} digest: ${digest}`)
93
+ this.#logger.debug({ reqId: req.id, calculated, digest }, 'Digest mismatch')
94
94
  throw createHttpError(400, 'Digest mismatch')
95
95
  }
96
96
  }
97
97
  const { method, headers } = req
98
- this.#logger.debug({ originalUrl }, 'original URL')
98
+ this.#logger.debug({ reqId: req.id, originalUrl }, 'original URL')
99
99
  const keyId = this.#signer.keyId(signature)
100
- this.#logger.debug({ keyId }, 'Signed with keyId')
100
+ this.#logger.debug({ reqId: req.id, keyId }, 'Signed with keyId')
101
101
  const ok = await this.#remoteKeyStorage.getPublicKey(keyId)
102
102
  if (!ok) {
103
103
  throw createHttpError(400, 'public key not found')
@@ -105,22 +105,22 @@ export class HTTPSignatureAuthenticator {
105
105
  let owner = ok.owner
106
106
  let publicKeyPem = ok.publicKeyPem
107
107
  let result = await this.#signer.validate(publicKeyPem, signature, method, originalUrl, headers)
108
- this.#logger.debug(`First validation result: ${result}`)
108
+ this.#logger.debug({ reqId: req.id, result }, 'First validation result')
109
109
  if (!result) {
110
110
  // May be key rotation. Try again with uncached key
111
111
  const ok2 = await this.#remoteKeyStorage.getPublicKey(keyId, false)
112
112
  if (ok2.publicKeyPem === ok.publicKeyPem) {
113
- this.#logger.debug('same keys')
113
+ this.#logger.debug({ reqId: req.id }, 'same keys')
114
114
  } else {
115
- this.#logger.debug('different keys')
115
+ this.#logger.debug({ reqId: req.id }, 'different keys')
116
116
  owner = ok2.owner
117
117
  publicKeyPem = ok2.publicKeyPem
118
118
  result = await this.#signer.validate(publicKeyPem, signature, method, originalUrl, headers)
119
- this.#logger.debug(`Validation result: ${result}`)
119
+ this.#logger.debug({ reqId: req.id, result }, 'Validation result')
120
120
  }
121
121
  }
122
122
  if (result) {
123
- this.#logger.debug(`Signature valid for ${keyId}`)
123
+ this.#logger.debug({ reqId: req.id, keyId }, 'Signature valid')
124
124
  req.auth = req.auth || {}
125
125
  req.auth.subject = owner
126
126
  return next()
@@ -131,7 +131,7 @@ export class HTTPSignatureAuthenticator {
131
131
 
132
132
  async #authenticateMessageSignature (signature, signatureInput, originalUrl, req, res, next) {
133
133
  this.#logger.debug(
134
- { signature, signatureInput, originalUrl },
134
+ { reqId: req.id, signature, signatureInput, originalUrl },
135
135
  'authenticating message signature'
136
136
  )
137
137
  const date = req.get('Date')
@@ -146,7 +146,7 @@ export class HTTPSignatureAuthenticator {
146
146
  }
147
147
  const calculated = await this.#digester.contentDigest(req.rawBodyText)
148
148
  if (!this.#digester.equals(digest, calculated)) {
149
- this.#logger.debug(`calculated: ${calculated} digest: ${digest}`)
149
+ this.#logger.debug({ reqId: req.id, calculated, digest }, 'Digest mismatch')
150
150
  throw createHttpError(400, 'Digest mismatch')
151
151
  }
152
152
  }
@@ -165,7 +165,7 @@ export class HTTPSignatureAuthenticator {
165
165
  if (!keyId) {
166
166
  throw createHttpError(400, 'no public key provided')
167
167
  }
168
- this.#logger.debug({ keyId }, 'Signed with keyId')
168
+ this.#logger.debug({ reqId: req.id, keyId }, 'Signed with keyId')
169
169
  const ok = await this.#remoteKeyStorage.getPublicKey(keyId)
170
170
  if (!ok) {
171
171
  throw createHttpError(400, 'public key not found')
@@ -173,22 +173,22 @@ export class HTTPSignatureAuthenticator {
173
173
  let owner = ok.owner
174
174
  let publicKeyPem = ok.publicKeyPem
175
175
  let result = await this.#messageSigner.validate(publicKeyPem, signatureInput, signature, method, url, headers)
176
- this.#logger.debug(`First validation result: ${result}`)
176
+ this.#logger.debug({ reqId: req.id, result }, 'First validation result')
177
177
  if (!result) {
178
178
  // May be key rotation. Try again with uncached key
179
179
  const ok2 = await this.#remoteKeyStorage.getPublicKey(keyId, false)
180
180
  if (ok2.publicKeyPem === ok.publicKeyPem) {
181
- this.#logger.debug('same keys')
181
+ this.#logger.debug({ reqId: req.id }, 'same keys')
182
182
  } else {
183
- this.#logger.debug('different keys')
183
+ this.#logger.debug({ reqId: req.id }, 'different keys')
184
184
  owner = ok2.owner
185
185
  publicKeyPem = ok2.publicKeyPem
186
186
  result = await this.#messageSigner.validate(publicKeyPem, signatureInput, signature, method, url, headers)
187
- this.#logger.debug(`Validation result: ${result}`)
187
+ this.#logger.debug({ reqId: req.id, result }, 'Validation result')
188
188
  }
189
189
  }
190
190
  if (result) {
191
- this.#logger.debug(`Signature valid for ${keyId}`)
191
+ this.#logger.debug({ reqId: req.id, keyId }, 'Signature valid')
192
192
  req.auth = req.auth || {}
193
193
  req.auth.subject = owner
194
194
  return next()
@@ -32,8 +32,8 @@ router.post('/user/:username/inbox', async (req, res, next) => {
32
32
  try {
33
33
  activity = await as2.import(req.body)
34
34
  } catch (err) {
35
- logger.warn('Failed to import activity', err)
36
- logger.debug('Request body', req.body)
35
+ logger.warn({ reqId: req.id, err }, 'Failed to import activity')
36
+ logger.debug({ reqId: req.id, body: req.body }, 'Request body')
37
37
  return next(createHttpError(400, 'Invalid request body'))
38
38
  }
39
39
 
@@ -67,7 +67,10 @@ router.post('/user/:username/inbox', async (req, res, next) => {
67
67
  return next(createHttpError(400, 'Activity already delivered'))
68
68
  }
69
69
 
70
- logger.info(`Activity ${activity.id} received at ${bot.username} inbox`)
70
+ logger.info(
71
+ { reqId: req.id, activity: activity.id, bot: bot.username },
72
+ 'Activity received at bot inbox'
73
+ )
71
74
 
72
75
  await deliverer.deliverTo(activity, bot)
73
76
 
@@ -37,7 +37,7 @@ router.post('/shared/proxy', async (req, res, next) => {
37
37
  try {
38
38
  obj = await client.get(id)
39
39
  } catch (err) {
40
- logger.warn({ err, id }, 'Error fetching object in proxy')
40
+ logger.warn({ reqId: req.id, err, id }, 'Error fetching object in proxy')
41
41
  return next(createHttpError(400, `Error fetching object ${id}`))
42
42
  }
43
43
 
@@ -40,8 +40,8 @@ router.post('/shared/inbox', async (req, res, next) => {
40
40
  try {
41
41
  activity = await as2.import(req.body)
42
42
  } catch (err) {
43
- logger.warn('Failed to import activity', err)
44
- logger.debug('Request body', req.body)
43
+ logger.warn({ reqId: req.id, err }, 'Failed to import activity')
44
+ logger.debug({ reqId: req.id, body: req.body }, 'Request body')
45
45
  return next(createHttpError(400, 'Invalid request body'))
46
46
  }
47
47
 
@@ -67,7 +67,10 @@ router.post('/shared/inbox', async (req, res, next) => {
67
67
  return next(createHttpError(400, 'No activity id found in activity'))
68
68
  }
69
69
 
70
- logger.info(`Activity ${activity.id} received at shared inbox`)
70
+ logger.info(
71
+ { reqId: req.id, activity: activity.id },
72
+ 'Activity received at shared inbox'
73
+ )
71
74
 
72
75
  await deliverer.intake(activity, subject)
73
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evanp/activitypub-bot",
3
- "version": "0.38.2",
3
+ "version": "0.38.3",
4
4
  "description": "server-side ActivityPub bot framework",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",