@fedify/fedify 2.0.0-dev.323 → 2.0.0-dev.372

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +8 -0
  2. package/dist/{builder-CvKuNW7P.js → builder-BxlBAtuD.js} +8 -3
  3. package/dist/compat/mod.d.cts +2 -2
  4. package/dist/compat/mod.d.ts +2 -2
  5. package/dist/compat/transformers.test.js +11 -11
  6. package/dist/{context-Zqld1re2.d.cts → context-Cf0-LmZC.d.cts} +92 -1
  7. package/dist/{context-CJO1oqSa.d.ts → context-liIe6DFH.d.ts} +92 -1
  8. package/dist/{deno-BTAi5-ur.js → deno-CDo9j5Hk.js} +1 -4
  9. package/dist/{docloader-D8dzb6AT.js → docloader-Cl-iMQFP.js} +2 -2
  10. package/dist/federation/builder.test.js +3 -3
  11. package/dist/federation/handler.test.js +11 -11
  12. package/dist/federation/idempotency.test.js +11 -11
  13. package/dist/federation/inbox.test.js +2 -2
  14. package/dist/federation/middleware.test.js +171 -11
  15. package/dist/federation/mod.cjs +5 -4
  16. package/dist/federation/mod.d.cts +3 -3
  17. package/dist/federation/mod.d.ts +3 -3
  18. package/dist/federation/mod.js +5 -5
  19. package/dist/federation/send.test.js +89 -6
  20. package/dist/federation/webfinger.test.js +11 -11
  21. package/dist/{http-BCfCt7nq.cjs → http-B8cUSIVv.cjs} +1 -4
  22. package/dist/{http-C4WANccp.js → http-BQhAaO-e.js} +2 -2
  23. package/dist/{http-C02fQ5SX.js → http-C_qj3I7F.js} +1 -4
  24. package/dist/{inbox-CdBcxHA7.js → inbox-B4kgSsVH.js} +1 -1
  25. package/dist/{key-BI6sqU5u.js → key-DtVs0UwP.js} +1 -1
  26. package/dist/{kv-cache-BLxaWwPk.js → kv-cache-CibadbOC.js} +1 -1
  27. package/dist/{kv-cache-Dk9UX_M2.cjs → kv-cache-CkfpyCN5.cjs} +1 -1
  28. package/dist/{ld-qTcTL2A4.js → ld-BLHZlaWL.js} +2 -2
  29. package/dist/{middleware-BhYGJwH9.js → middleware-BDQ8PDFx.js} +4 -4
  30. package/dist/{middleware-DG4UsFBP.js → middleware-BQigFVlt.js} +11 -11
  31. package/dist/{middleware-DaOdxVOc.js → middleware-C5W9b9D9.js} +154 -93
  32. package/dist/{middleware-LQKxYF7X.js → middleware-CEcrmJf2.js} +189 -89
  33. package/dist/middleware-COrE1spG.cjs +12 -0
  34. package/dist/{middleware-nW8ONmt3.cjs → middleware-DfAuhaf7.cjs} +194 -88
  35. package/dist/{mod-Bpuc-q64.d.ts → mod-B9_l3te3.d.ts} +1 -1
  36. package/dist/{mod-CKtAEVny.d.cts → mod-Do_sZWAA.d.cts} +1 -1
  37. package/dist/{mod-C92O3FpJ.d.ts → mod-Dquroqiv.d.ts} +1 -1
  38. package/dist/{mod-DFWeUq2q.d.cts → mod-H3ScYaOb.d.cts} +1 -1
  39. package/dist/mod.cjs +6 -4
  40. package/dist/mod.d.cts +5 -5
  41. package/dist/mod.d.ts +5 -5
  42. package/dist/mod.js +6 -5
  43. package/dist/nodeinfo/handler.test.js +11 -11
  44. package/dist/{owner-Cfmtlwoe.js → owner-BwS4q7BU.js} +1 -1
  45. package/dist/{proof-OjMPhNWs.js → proof-Cq8LNpQ3.js} +1 -1
  46. package/dist/{proof-BoqEqbih.cjs → proof-EVy7shg_.cjs} +1 -1
  47. package/dist/{proof-Bc8ULrzP.js → proof-N5F9c402.js} +2 -2
  48. package/dist/{send-BKW3wSXo.js → send-DpOe6hgL.js} +38 -4
  49. package/dist/sig/http.test.js +3 -3
  50. package/dist/sig/key.test.js +2 -2
  51. package/dist/sig/ld.test.js +3 -3
  52. package/dist/sig/mod.cjs +2 -2
  53. package/dist/sig/mod.js +2 -2
  54. package/dist/sig/owner.test.js +3 -3
  55. package/dist/sig/proof.test.js +3 -3
  56. package/dist/testing/mod.d.ts +80 -0
  57. package/dist/utils/docloader.test.js +4 -4
  58. package/dist/utils/mod.cjs +2 -2
  59. package/dist/utils/mod.js +2 -2
  60. package/package.json +8 -8
  61. package/dist/middleware-Dsrm1uhx.cjs +0 -12
@@ -3,24 +3,24 @@
3
3
  import { URLPattern } from "urlpattern-polyfill";
4
4
  globalThis.addEventListener = () => {};
5
5
 
6
- import { deno_default } from "./deno-BTAi5-ur.js";
6
+ import { deno_default } from "./deno-CDo9j5Hk.js";
7
7
  import { getNodeInfo } from "./client-Dg7OfUDA.js";
8
8
  import { RouterError } from "./router-D9eI0s4b.js";
9
9
  import { nodeInfoToJson } from "./types-CPz01LGH.js";
10
- import { exportJwk, importJwk, validateCryptoKey } from "./key-BI6sqU5u.js";
11
- import { verifyRequest } from "./http-C4WANccp.js";
12
- import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-qTcTL2A4.js";
13
- import { doesActorOwnKey, getKeyOwner } from "./owner-Cfmtlwoe.js";
14
- import { signObject, verifyObject } from "./proof-Bc8ULrzP.js";
15
- import { getAuthenticatedDocumentLoader } from "./docloader-D8dzb6AT.js";
10
+ import { exportJwk, importJwk, validateCryptoKey } from "./key-DtVs0UwP.js";
11
+ import { verifyRequest } from "./http-BQhAaO-e.js";
12
+ import { detachSignature, hasSignature, signJsonLd, verifyJsonLd } from "./ld-BLHZlaWL.js";
13
+ import { doesActorOwnKey, getKeyOwner } from "./owner-BwS4q7BU.js";
14
+ import { signObject, verifyObject } from "./proof-N5F9c402.js";
15
+ import { getAuthenticatedDocumentLoader } from "./docloader-Cl-iMQFP.js";
16
16
  import { kvCache } from "./kv-cache-B__dHl7g.js";
17
- import { routeActivity } from "./inbox-CdBcxHA7.js";
18
- import { FederationBuilderImpl } from "./builder-CvKuNW7P.js";
17
+ import { routeActivity } from "./inbox-B4kgSsVH.js";
18
+ import { FederationBuilderImpl } from "./builder-BxlBAtuD.js";
19
19
  import { buildCollectionSynchronizationHeader } from "./collection-CcnIw1qY.js";
20
20
  import { KvKeyCache } from "./keycache-DRxpZ5r9.js";
21
21
  import { acceptsJsonLd } from "./negotiation-5NPJL6zp.js";
22
22
  import { createExponentialBackoffPolicy } from "./retry-D4GJ670a.js";
23
- import { extractInboxes, sendActivity } from "./send-BKW3wSXo.js";
23
+ import { SendActivityError, extractInboxes, sendActivity } from "./send-DpOe6hgL.js";
24
24
  import { getLogger, withContext } from "@logtape/logtape";
25
25
  import { Activity, Collection, CollectionPage, CryptographicKey, Link, Multikey, Object as Object$1, OrderedCollection, OrderedCollectionPage, getTypeId, lookupObject, traverseCollection } from "@fedify/vocab";
26
26
  import { getDocumentLoader } from "@fedify/vocab-runtime";
@@ -1307,12 +1307,13 @@ var FederationImpl = class extends FederationBuilderImpl {
1307
1307
  allowPrivateAddress;
1308
1308
  userAgent;
1309
1309
  onOutboxError;
1310
+ permanentFailureStatusCodes;
1310
1311
  signatureTimeWindow;
1311
1312
  skipSignatureVerification;
1312
1313
  outboxRetryPolicy;
1313
1314
  inboxRetryPolicy;
1314
1315
  activityTransformers;
1315
- tracerProvider;
1316
+ _tracerProvider;
1316
1317
  firstKnock;
1317
1318
  constructor(options) {
1318
1319
  super();
@@ -1388,14 +1389,18 @@ var FederationImpl = class extends FederationBuilderImpl {
1388
1389
  }));
1389
1390
  this.userAgent = userAgent;
1390
1391
  this.onOutboxError = options.onOutboxError;
1392
+ this.permanentFailureStatusCodes = options.permanentFailureStatusCodes ?? [404, 410];
1391
1393
  this.signatureTimeWindow = options.signatureTimeWindow ?? { hours: 1 };
1392
1394
  this.skipSignatureVerification = options.skipSignatureVerification ?? false;
1393
1395
  this.outboxRetryPolicy = options.outboxRetryPolicy ?? createExponentialBackoffPolicy();
1394
1396
  this.inboxRetryPolicy = options.inboxRetryPolicy ?? createExponentialBackoffPolicy();
1395
1397
  this.activityTransformers = options.activityTransformers ?? getDefaultActivityTransformers();
1396
- this.tracerProvider = options.tracerProvider ?? trace.getTracerProvider();
1398
+ this._tracerProvider = options.tracerProvider;
1397
1399
  this.firstKnock = options.firstKnock;
1398
1400
  }
1401
+ get tracerProvider() {
1402
+ return this._tracerProvider ?? trace.getTracerProvider();
1403
+ }
1399
1404
  _initializeRouter() {
1400
1405
  this.router.add("/.well-known/webfinger", "webfinger");
1401
1406
  this.router.add("/.well-known/nodeinfo", "nodeInfoJrd");
@@ -1436,18 +1441,24 @@ var FederationImpl = class extends FederationBuilderImpl {
1436
1441
  kind: SpanKind.CONSUMER,
1437
1442
  attributes: { "activitypub.activity.type": message.activityType }
1438
1443
  }, extractedContext, async (span) => {
1439
- if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1440
- try {
1441
- await this.#listenFanoutMessage(contextData, message);
1442
- } catch (e) {
1443
- span.setStatus({
1444
- code: SpanStatusCode.ERROR,
1445
- message: String(e)
1446
- });
1447
- throw e;
1448
- } finally {
1449
- span.end();
1450
- }
1444
+ const spanCtx = span.spanContext();
1445
+ return await withContext({
1446
+ traceId: spanCtx.traceId,
1447
+ spanId: spanCtx.spanId
1448
+ }, async () => {
1449
+ if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1450
+ try {
1451
+ await this.#listenFanoutMessage(contextData, message);
1452
+ } catch (e) {
1453
+ span.setStatus({
1454
+ code: SpanStatusCode.ERROR,
1455
+ message: String(e)
1456
+ });
1457
+ throw e;
1458
+ } finally {
1459
+ span.end();
1460
+ }
1461
+ });
1451
1462
  });
1452
1463
  else if (message.type === "outbox") await tracer.startActiveSpan("activitypub.outbox", {
1453
1464
  kind: SpanKind.CONSUMER,
@@ -1456,34 +1467,46 @@ var FederationImpl = class extends FederationBuilderImpl {
1456
1467
  "activitypub.activity.retries": message.attempt
1457
1468
  }
1458
1469
  }, extractedContext, async (span) => {
1459
- if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1460
- try {
1461
- await this.#listenOutboxMessage(contextData, message, span);
1462
- } catch (e) {
1463
- span.setStatus({
1464
- code: SpanStatusCode.ERROR,
1465
- message: String(e)
1466
- });
1467
- throw e;
1468
- } finally {
1469
- span.end();
1470
- }
1470
+ const spanCtx = span.spanContext();
1471
+ return await withContext({
1472
+ traceId: spanCtx.traceId,
1473
+ spanId: spanCtx.spanId
1474
+ }, async () => {
1475
+ if (message.activityId != null) span.setAttribute("activitypub.activity.id", message.activityId);
1476
+ try {
1477
+ await this.#listenOutboxMessage(contextData, message, span);
1478
+ } catch (e) {
1479
+ span.setStatus({
1480
+ code: SpanStatusCode.ERROR,
1481
+ message: String(e)
1482
+ });
1483
+ throw e;
1484
+ } finally {
1485
+ span.end();
1486
+ }
1487
+ });
1471
1488
  });
1472
1489
  else if (message.type === "inbox") await tracer.startActiveSpan("activitypub.inbox", {
1473
1490
  kind: SpanKind.CONSUMER,
1474
1491
  attributes: { "activitypub.shared_inbox": message.identifier == null }
1475
1492
  }, extractedContext, async (span) => {
1476
- try {
1477
- await this.#listenInboxMessage(contextData, message, span);
1478
- } catch (e) {
1479
- span.setStatus({
1480
- code: SpanStatusCode.ERROR,
1481
- message: String(e)
1482
- });
1483
- throw e;
1484
- } finally {
1485
- span.end();
1486
- }
1493
+ const spanCtx = span.spanContext();
1494
+ return await withContext({
1495
+ traceId: spanCtx.traceId,
1496
+ spanId: spanCtx.spanId
1497
+ }, async () => {
1498
+ try {
1499
+ await this.#listenInboxMessage(contextData, message, span);
1500
+ } catch (e) {
1501
+ span.setStatus({
1502
+ code: SpanStatusCode.ERROR,
1503
+ message: String(e)
1504
+ });
1505
+ throw e;
1506
+ } finally {
1507
+ span.end();
1508
+ }
1509
+ });
1487
1510
  });
1488
1511
  });
1489
1512
  }
@@ -1570,13 +1593,44 @@ var FederationImpl = class extends FederationBuilderImpl {
1570
1593
  tracerProvider: this.tracerProvider
1571
1594
  });
1572
1595
  try {
1573
- this.onOutboxError?.(error, activity);
1596
+ await this.onOutboxError?.(error, activity);
1574
1597
  } catch (error$1) {
1575
1598
  logger$2.error("An unexpected error occurred in onError handler:\n{error}", {
1576
1599
  ...logData,
1577
1600
  error: error$1
1578
1601
  });
1579
1602
  }
1603
+ if (error instanceof SendActivityError && this.permanentFailureStatusCodes.includes(error.statusCode)) {
1604
+ logger$2.warn("Permanent delivery failure for activity {activityId} to {inbox} ({status}); not retrying.", {
1605
+ ...logData,
1606
+ status: error.statusCode
1607
+ });
1608
+ if (this.outboxPermanentFailureHandler != null) {
1609
+ const ctx = this.#createContext(new URL(message.baseUrl), _, { documentLoader: this.documentLoaderFactory(loaderOptions) });
1610
+ try {
1611
+ await this.outboxPermanentFailureHandler(ctx, {
1612
+ inbox: new URL(message.inbox),
1613
+ activity,
1614
+ error,
1615
+ statusCode: error.statusCode,
1616
+ actorIds: (message.actorIds ?? []).flatMap((id) => {
1617
+ try {
1618
+ return [new URL(id)];
1619
+ } catch {
1620
+ logger$2.warn("Invalid actorId URL in OutboxMessage: {id}", { id });
1621
+ return [];
1622
+ }
1623
+ })
1624
+ });
1625
+ } catch (handlerError) {
1626
+ logger$2.error("An unexpected error occurred in outboxPermanentFailureHandler:\n{error}", {
1627
+ ...logData,
1628
+ error: handlerError
1629
+ });
1630
+ }
1631
+ }
1632
+ return;
1633
+ }
1580
1634
  if (this.outboxQueue?.nativeRetrial) {
1581
1635
  logger$2.error("Failed to send activity {activityId} to {inbox}; backend will handle retry:\n{error}", {
1582
1636
  ...logData,
@@ -1867,6 +1921,7 @@ var FederationImpl = class extends FederationBuilderImpl {
1867
1921
  activityType: getTypeId(activity).href,
1868
1922
  inbox,
1869
1923
  sharedInbox: inboxes[inbox].sharedInbox,
1924
+ actorIds: [...inboxes[inbox].actorIds],
1870
1925
  started: (/* @__PURE__ */ new Date()).toISOString(),
1871
1926
  attempt: 0,
1872
1927
  headers: collectionSync == null ? {} : { "Collection-Synchronization": await buildCollectionSynchronizationHeader(collectionSync, inboxes[inbox].actorIds) },
@@ -1924,54 +1979,60 @@ var FederationImpl = class extends FederationBuilderImpl {
1924
1979
  [ATTR_URL_FULL]: request.url
1925
1980
  }
1926
1981
  }, async (span) => {
1927
- const logger$2 = getLogger([
1928
- "fedify",
1929
- "federation",
1930
- "http"
1931
- ]);
1932
- if (span.isRecording()) for (const [k, v] of request.headers) span.setAttribute(ATTR_HTTP_REQUEST_HEADER(k), [v]);
1933
- let response;
1934
- try {
1935
- response = await this.#fetch(request, {
1936
- ...options,
1937
- span,
1938
- tracer
1939
- });
1940
- if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
1941
- } catch (error) {
1942
- span.setStatus({
1943
- code: SpanStatusCode.ERROR,
1944
- message: `${error}`
1945
- });
1982
+ const spanCtx = span.spanContext();
1983
+ return await withContext({
1984
+ traceId: spanCtx.traceId,
1985
+ spanId: spanCtx.spanId
1986
+ }, async () => {
1987
+ const logger$2 = getLogger([
1988
+ "fedify",
1989
+ "federation",
1990
+ "http"
1991
+ ]);
1992
+ if (span.isRecording()) for (const [k, v] of request.headers) span.setAttribute(ATTR_HTTP_REQUEST_HEADER(k), [v]);
1993
+ let response;
1994
+ try {
1995
+ response = await this.#fetch(request, {
1996
+ ...options,
1997
+ span,
1998
+ tracer
1999
+ });
2000
+ if (acceptsJsonLd(request)) response.headers.set("Vary", "Accept");
2001
+ } catch (error) {
2002
+ span.setStatus({
2003
+ code: SpanStatusCode.ERROR,
2004
+ message: `${error}`
2005
+ });
2006
+ span.end();
2007
+ logger$2.error("An error occurred while serving request {method} {url}: {error}", {
2008
+ method: request.method,
2009
+ url: request.url,
2010
+ error
2011
+ });
2012
+ throw error;
2013
+ }
2014
+ if (span.isRecording()) {
2015
+ span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
2016
+ for (const [k, v] of response.headers) span.setAttribute(ATTR_HTTP_RESPONSE_HEADER(k), [v]);
2017
+ span.setStatus({
2018
+ code: response.status >= 500 ? SpanStatusCode.ERROR : SpanStatusCode.UNSET,
2019
+ message: response.statusText
2020
+ });
2021
+ }
1946
2022
  span.end();
1947
- logger$2.error("An error occurred while serving request {method} {url}: {error}", {
2023
+ const url = new URL(request.url);
2024
+ const logTpl = "{method} {path}: {status}";
2025
+ const values = {
1948
2026
  method: request.method,
2027
+ path: `${url.pathname}${url.search}`,
1949
2028
  url: request.url,
1950
- error
1951
- });
1952
- throw error;
1953
- }
1954
- if (span.isRecording()) {
1955
- span.setAttribute(ATTR_HTTP_RESPONSE_STATUS_CODE, response.status);
1956
- for (const [k, v] of response.headers) span.setAttribute(ATTR_HTTP_RESPONSE_HEADER(k), [v]);
1957
- span.setStatus({
1958
- code: response.status >= 500 ? SpanStatusCode.ERROR : SpanStatusCode.UNSET,
1959
- message: response.statusText
1960
- });
1961
- }
1962
- span.end();
1963
- const url = new URL(request.url);
1964
- const logTpl = "{method} {path}: {status}";
1965
- const values = {
1966
- method: request.method,
1967
- path: `${url.pathname}${url.search}`,
1968
- url: request.url,
1969
- status: response.status
1970
- };
1971
- if (response.status >= 500) logger$2.error(logTpl, values);
1972
- else if (response.status >= 400) logger$2.warn(logTpl, values);
1973
- else logger$2.info(logTpl, values);
1974
- return response;
2029
+ status: response.status
2030
+ };
2031
+ if (response.status >= 500) logger$2.error(logTpl, values);
2032
+ else if (response.status >= 400) logger$2.warn(logTpl, values);
2033
+ else logger$2.info(logTpl, values);
2034
+ return response;
2035
+ });
1975
2036
  });
1976
2037
  });
1977
2038
  }