@fedify/fedify 2.2.0-pr.695.16 → 2.2.0-pr.697.17

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 (63) hide show
  1. package/dist/activity-listener-Ck3JZ_hR.mjs +40 -0
  2. package/dist/{builder-7PVCiLiR.mjs → builder-0VkYL-Be.mjs} +57 -7
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/transformers.test.mjs +1 -1
  6. package/dist/{context-78ecvxf5.d.ts → context-BGrYMSTk.d.ts} +143 -1
  7. package/dist/{context-DYDPdoCb.d.cts → context-CMUd4wy0.d.cts} +143 -1
  8. package/dist/{context-Juj6bdHC.mjs → context-Dk_tacqz.mjs} +17 -2
  9. package/dist/{deno-vxcWcxQS.mjs → deno-ZTLy21O_.mjs} +1 -1
  10. package/dist/{docloader-D7q0-Xef.mjs → docloader-qLB9fFVV.mjs} +2 -2
  11. package/dist/federation/builder.test.mjs +25 -1
  12. package/dist/federation/handler.test.mjs +369 -8
  13. package/dist/federation/idempotency.test.mjs +2 -2
  14. package/dist/federation/inbox.test.mjs +3 -3
  15. package/dist/federation/middleware.test.mjs +510 -8
  16. package/dist/federation/mod.cjs +1 -1
  17. package/dist/federation/mod.d.cts +3 -3
  18. package/dist/federation/mod.d.ts +3 -3
  19. package/dist/federation/mod.js +1 -1
  20. package/dist/federation/send.test.mjs +3 -3
  21. package/dist/federation/webfinger.test.mjs +2 -2
  22. package/dist/{http-JxF7bG0o.cjs → http-BLuuf-Rt.cjs} +1 -1
  23. package/dist/{http-RZPxDWq5.mjs → http-CFmrJbuT.mjs} +2 -2
  24. package/dist/{http-D-MhhYUF.js → http-CqkZgsp_.js} +1 -1
  25. package/dist/{key-CGx_dDkX.mjs → key-DVFCI5om.mjs} +1 -1
  26. package/dist/{kv-cache-C2gdVgvb.cjs → kv-cache-BlXew67e.cjs} +1 -1
  27. package/dist/{kv-cache-D84Mk0fZ.js → kv-cache-Dgsvz3PC.js} +1 -1
  28. package/dist/{ld-wup-liFO.mjs → ld-N69KBAlI.mjs} +26 -3
  29. package/dist/{middleware-Bn75dPug.cjs → middleware-B0BqhA1u.cjs} +676 -323
  30. package/dist/{middleware-RF-sUfTr.js → middleware-BpSfJf2S.js} +670 -322
  31. package/dist/{middleware-CXOVT4Ph.cjs → middleware-CUe96Oxe.cjs} +1 -1
  32. package/dist/{middleware-wdfeWjRJ.mjs → middleware-DDXN5eBU.mjs} +1 -1
  33. package/dist/{middleware-BjVx-_bv.mjs → middleware-DbCHS-GH.mjs} +612 -180
  34. package/dist/{mod-CEohtXhV.d.cts → mod-BcJHeuv1.d.cts} +1 -1
  35. package/dist/{mod-CokIUYDr.d.ts → mod-CJXfyw7v.d.ts} +1 -1
  36. package/dist/{mod-DvxszxXC.d.ts → mod-CR8soWa9.d.ts} +18 -1
  37. package/dist/{mod-DoJBjjnO.d.cts → mod-Cr3f-ACa.d.cts} +18 -1
  38. package/dist/mod.cjs +6 -4
  39. package/dist/mod.d.cts +5 -5
  40. package/dist/mod.d.ts +5 -5
  41. package/dist/mod.js +5 -5
  42. package/dist/nodeinfo/handler.test.mjs +2 -2
  43. package/dist/{owner-q2mUMM9a.mjs → owner-DGdkXeF5.mjs} +2 -2
  44. package/dist/{proof-CirP9OSd.js → proof-BtFhWZuV.js} +54 -2
  45. package/dist/{proof--CpZsF_p.mjs → proof-C50gFNxj.mjs} +32 -3
  46. package/dist/{proof-_Zyfqyce.cjs → proof-DwRcU3OF.cjs} +61 -3
  47. package/dist/{send-CVJfx7bF.mjs → send-BlHiNsZI.mjs} +2 -2
  48. package/dist/sig/http.test.mjs +2 -2
  49. package/dist/sig/key.test.mjs +1 -1
  50. package/dist/sig/ld.test.mjs +44 -2
  51. package/dist/sig/mod.cjs +4 -2
  52. package/dist/sig/mod.d.cts +2 -2
  53. package/dist/sig/mod.d.ts +2 -2
  54. package/dist/sig/mod.js +3 -3
  55. package/dist/sig/owner.test.mjs +1 -1
  56. package/dist/sig/proof.test.mjs +46 -2
  57. package/dist/testing/mod.d.mts +149 -1
  58. package/dist/testing/mod.mjs +2 -2
  59. package/dist/utils/docloader.test.mjs +2 -2
  60. package/dist/utils/mod.cjs +1 -1
  61. package/dist/utils/mod.js +1 -1
  62. package/package.json +5 -5
  63. package/dist/inbox-CmYvcSMM.mjs +0 -179
@@ -5,9 +5,9 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-CGx_dDkX.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-DVFCI5om.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
10
- import { a as signJsonLd, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-wup-liFO.mjs";
10
+ import { a as signJsonLd, i as hasSignatureLike, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-N69KBAlI.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { encodeBase64 } from "byte-encodings/base64";
@@ -55,6 +55,48 @@ test("signJsonLd()", async () => {
55
55
  contextLoader: mockDocumentLoader
56
56
  }));
57
57
  });
58
+ test("hasSignatureLike()", () => {
59
+ assert(hasSignatureLike({ signature: {
60
+ type: "RsaSignature2017",
61
+ creator: "https://example.com/users/alice#main-key",
62
+ signatureValue: "signature"
63
+ } }));
64
+ assert(hasSignatureLike({ signature: {
65
+ type: "Ed25519Signature2020",
66
+ verificationMethod: "https://example.com/users/alice#main-key",
67
+ jws: "signature"
68
+ } }));
69
+ assert(hasSignatureLike({ signature: {
70
+ type: "Ed25519Signature2020",
71
+ verificationMethod: { id: "https://example.com/users/alice#main-key" },
72
+ jws: "signature"
73
+ } }));
74
+ assert(hasSignatureLike({ signature: {
75
+ type: "Ed25519Signature2020",
76
+ verificationMethod: [{ id: "https://example.com/users/alice#main-key" }],
77
+ jws: "signature"
78
+ } }));
79
+ assert(hasSignatureLike({ signature: {
80
+ type: "Ed25519Signature2020",
81
+ verificationMethod: { "@id": "https://example.com/users/alice#main-key" },
82
+ jws: "signature"
83
+ } }));
84
+ assert(hasSignatureLike({ signature: [{
85
+ type: "Ed25519Signature2020",
86
+ verificationMethod: { "@id": "https://example.com/users/alice#main-key" },
87
+ jws: "signature"
88
+ }] }));
89
+ assert(hasSignatureLike({ signature: {
90
+ type: ["Ed25519Signature2020"],
91
+ verificationMethod: "https://example.com/users/alice#main-key",
92
+ jws: "signature"
93
+ } }));
94
+ assertFalse(hasSignatureLike({ signature: {
95
+ type: "Ed25519Signature2020",
96
+ verificationMethod: "https://example.com/users/alice#main-key"
97
+ } }));
98
+ assertFalse(hasSignatureLike(null));
99
+ });
58
100
  const document = {
59
101
  "@context": ["https://www.w3.org/ns/activitystreams", {
60
102
  "ostatus": "http://ostatus.org#",
package/dist/sig/mod.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_http = require("../http-JxF7bG0o.cjs");
5
- const require_proof = require("../proof-_Zyfqyce.cjs");
4
+ const require_http = require("../http-BLuuf-Rt.cjs");
5
+ const require_proof = require("../proof-DwRcU3OF.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
@@ -15,6 +15,8 @@ exports.formatAcceptSignature = require_http.formatAcceptSignature;
15
15
  exports.fulfillAcceptSignature = require_http.fulfillAcceptSignature;
16
16
  exports.generateCryptoKeyPair = require_http.generateCryptoKeyPair;
17
17
  exports.getKeyOwner = require_proof.getKeyOwner;
18
+ exports.hasProofLike = require_proof.hasProofLike;
19
+ exports.hasSignatureLike = require_proof.hasSignatureLike;
18
20
  exports.importJwk = require_http.importJwk;
19
21
  exports.parseAcceptSignature = require_http.parseAcceptSignature;
20
22
  exports.signJsonLd = require_proof.signJsonLd;
@@ -1,4 +1,4 @@
1
1
  import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-CrGuipxe.cjs";
2
2
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-CptqhsOy.cjs";
3
- import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-DoJBjjnO.cjs";
4
- export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
3
+ import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-Cr3f-ACa.cjs";
4
+ export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
package/dist/sig/mod.d.ts CHANGED
@@ -2,5 +2,5 @@ import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-aQzN9Ayi.js";
4
4
  import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-74ARJ5TL.js";
5
- import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-DvxszxXC.js";
6
- export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
5
+ import { _ as hasSignatureLike, a as createProof, b as verifySignature, c as verifyObject, d as SignJsonLdOptions, f as VerifyJsonLdOptions, g as detachSignature, h as createSignature, i as VerifyProofOptions, l as verifyProof, m as attachSignature, n as SignObjectOptions, o as hasProofLike, p as VerifySignatureOptions, r as VerifyObjectOptions, s as signObject, t as CreateProofOptions, u as CreateSignatureOptions, v as signJsonLd, y as verifyJsonLd } from "../mod-CR8soWa9.js";
6
+ export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-D-MhhYUF.js";
4
- import { a as doesActorOwnKey, c as createSignature, d as signJsonLd, f as verifyJsonLd, i as verifyProof, l as detachSignature, n as signObject, o as getKeyOwner, p as verifySignature, r as verifyObject, s as attachSignature, t as createProof } from "../proof-CirP9OSd.js";
5
- export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
3
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-CqkZgsp_.js";
4
+ import { a as verifyProof, c as attachSignature, d as hasSignatureLike, f as signJsonLd, i as verifyObject, l as createSignature, m as verifySignature, n as hasProofLike, o as doesActorOwnKey, p as verifyJsonLd, r as signObject, s as getKeyOwner, t as createProof, u as detachSignature } from "../proof-BtFhWZuV.js";
5
+ export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import "../std__assert-Duiq_YC9.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-q2mUMM9a.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DGdkXeF5.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
12
12
  //#region src/sig/owner.test.ts
@@ -3,10 +3,11 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import "../std__assert-Duiq_YC9.mjs";
6
- import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
+ import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
+ import { t as assert } from "../assert-ddO5KLpe.mjs";
8
9
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
9
- import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof--CpZsF_p.mjs";
10
+ import { a as verifyProof, i as verifyObject, n as hasProofLike, r as signObject, t as createProof } from "../proof-C50gFNxj.mjs";
10
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
11
12
  import { Create, DataIntegrityProof, Multikey, Note, Place } from "@fedify/vocab";
12
13
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";
@@ -151,6 +152,49 @@ test("signObject()", async () => {
151
152
  contextLoader: mockDocumentLoader
152
153
  }), TypeError, "Unsupported algorithm");
153
154
  });
155
+ test("hasProofLike()", () => {
156
+ assert(hasProofLike({ proof: {
157
+ type: "DataIntegrityProof",
158
+ verificationMethod: "https://example.com/users/alice#main-key",
159
+ proofPurpose: "assertionMethod",
160
+ proofValue: "signature"
161
+ } }));
162
+ assert(hasProofLike({ proof: {
163
+ type: "DataIntegrityProof",
164
+ verificationMethod: { id: "https://example.com/users/alice#main-key" },
165
+ proofPurpose: "assertionMethod",
166
+ proofValue: "signature"
167
+ } }));
168
+ assert(hasProofLike({ proof: [{
169
+ type: "DataIntegrityProof",
170
+ verificationMethod: { id: "https://example.com/users/alice#main-key" },
171
+ proofPurpose: "assertionMethod",
172
+ proofValue: "signature"
173
+ }] }));
174
+ assert(hasProofLike({ proof: {
175
+ type: ["https://w3id.org/security#DataIntegrityProof"],
176
+ verificationMethod: [{ "@id": "https://example.com/users/alice#main-key" }],
177
+ proofPurpose: { "@id": "https://w3id.org/security#assertionMethod" },
178
+ proofValue: "signature"
179
+ } }));
180
+ assert(hasProofLike({ "https://w3id.org/security#proof": {
181
+ type: "DataIntegrityProof",
182
+ verificationMethod: { "@id": "https://example.com/users/alice#main-key" },
183
+ proofPurpose: { "@id": "https://w3id.org/security#assertionMethod" },
184
+ proofValue: "signature"
185
+ } }));
186
+ assert(hasProofLike({ "https://w3id.org/security#proof": [{
187
+ "@type": ["https://w3id.org/security#DataIntegrityProof"],
188
+ "https://w3id.org/security#verificationMethod": [{ "@id": "https://example.com/users/alice#main-key" }],
189
+ "https://w3id.org/security#proofPurpose": [{ "@id": "https://w3id.org/security#assertionMethod" }],
190
+ "https://w3id.org/security#proofValue": [{ "@value": "signature" }]
191
+ }] }));
192
+ assertFalse(hasProofLike({ proof: {
193
+ type: "DataIntegrityProof",
194
+ verificationMethod: { id: "https://example.com/users/alice#main-key" },
195
+ proofPurpose: "assertionMethod"
196
+ } }));
197
+ });
154
198
  test("verifyProof()", async () => {
155
199
  const cache = {};
156
200
  const options = {
@@ -393,6 +393,16 @@ type CollectionCursor<TContext extends Context<TContextData>, TContextData, TFil
393
393
  * @param activity The activity that was received.
394
394
  */
395
395
  type InboxListener<TContextData, TActivity extends Activity> = (context: InboxContext<TContextData>, activity: TActivity) => void | Promise<void>;
396
+ /**
397
+ * A callback that listens for activities in an outbox.
398
+ *
399
+ * @template TContextData The context data to pass to the {@link Context}.
400
+ * @template TActivity The type of activity to listen for.
401
+ * @param context The outbox context.
402
+ * @param activity The activity that was received.
403
+ * @since 2.2.0
404
+ */
405
+ type OutboxListener<TContextData, TActivity extends Activity> = (context: OutboxContext<TContextData>, activity: TActivity) => void | Promise<void>;
396
406
  /**
397
407
  * The reason why an incoming activity could not be verified.
398
408
  *
@@ -423,6 +433,15 @@ type UnverifiedActivityHandler<TContextData> = (context: RequestContext<TContext
423
433
  * @param context The inbox context.
424
434
  */
425
435
  type InboxErrorHandler<TContextData> = (context: Context<TContextData>, error: Error) => void | Promise<void>;
436
+ /**
437
+ * A callback that handles errors in an outbox listener.
438
+ *
439
+ * @template TContextData The context data to pass to the {@link Context}.
440
+ * @param context The outbox context.
441
+ * @param error The error that occurred.
442
+ * @since 2.2.0
443
+ */
444
+ type OutboxListenerErrorHandler<TContextData> = (context: OutboxContext<TContextData>, error: Error) => void | Promise<void>;
426
445
  /**
427
446
  * A callback that dispatches the key pair for the authenticated document loader
428
447
  * of the {@link Context} passed to the shared inbox listener.
@@ -781,6 +800,32 @@ interface Federatable<TContextData> {
781
800
  * @throws {@link RouterError} Thrown if the path pattern is invalid.
782
801
  */
783
802
  setOutboxDispatcher(path: `${string}${Rfc6570Expression<"identifier">}${string}`, dispatcher: CollectionDispatcher<Activity, RequestContext<TContextData>, TContextData, void>): CollectionCallbackSetters<RequestContext<TContextData>, TContextData, void>;
803
+ /**
804
+ * Assigns the URL path for the outbox and starts setting outbox listeners.
805
+ *
806
+ * @example
807
+ * ``` typescript
808
+ * federation
809
+ * .setOutboxListeners("/users/{identifier}/outbox")
810
+ * .on(Activity, async (ctx, activity) => {
811
+ * await ctx.sendActivity({ identifier: ctx.identifier }, "followers", activity);
812
+ * })
813
+ * .authorize(async (ctx, identifier) => {
814
+ * return ctx.request.headers.get("authorization") === `Bearer ${identifier}`;
815
+ * });
816
+ * ```
817
+ *
818
+ * @param outboxPath The URI path pattern for the outbox. The syntax is based
819
+ * on URI Template
820
+ * ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The
821
+ * path must have one variable: `{identifier}`. If an
822
+ * outbox dispatcher is configured, this path must match
823
+ * the outbox dispatcher path.
824
+ * @returns An object to register outbox listeners.
825
+ * @throws {RouterError} Thrown if the path pattern is invalid.
826
+ * @since 2.2.0
827
+ */
828
+ setOutboxListeners(outboxPath: `${string}${Rfc6570Expression<"identifier">}${string}`): OutboxListenerSetters<TContextData>;
784
829
  /**
785
830
  * Registers a following collection dispatcher.
786
831
  * @param path The URI path pattern for the following collection. The syntax
@@ -1168,6 +1213,38 @@ type IdempotencyStrategy = "global" | "per-origin" | "per-inbox";
1168
1213
  * @since 1.9.0
1169
1214
  */
1170
1215
  type IdempotencyKeyCallback<TContextData> = (ctx: InboxContext<TContextData>, activity: Activity) => string | null | Promise<string | null>;
1216
+ /**
1217
+ * Registry for outbox listeners for different activity types.
1218
+ * @since 2.2.0
1219
+ */
1220
+ interface OutboxListenerSetters<TContextData> {
1221
+ /**
1222
+ * Registers a listener for a specific incoming activity type.
1223
+ *
1224
+ * @param type A subclass of {@link Activity} to listen to.
1225
+ * @param listener A callback to handle an incoming activity.
1226
+ * @returns The setters object so that settings can be chained.
1227
+ * @since 2.2.0
1228
+ */
1229
+ on<TActivity extends Activity>(type: new (...args: any[]) => TActivity, listener: OutboxListener<TContextData, TActivity>): OutboxListenerSetters<TContextData>;
1230
+ /**
1231
+ * Registers an error handler for outbox listeners. Any exceptions thrown
1232
+ * from the listeners are caught and passed to this handler.
1233
+ *
1234
+ * @param handler A callback to handle an error.
1235
+ * @returns The setters object so that settings can be chained.
1236
+ * @since 2.2.0
1237
+ */
1238
+ onError(handler: OutboxListenerErrorHandler<TContextData>): OutboxListenerSetters<TContextData>;
1239
+ /**
1240
+ * Registers a callback to authorize POST requests to the outbox.
1241
+ *
1242
+ * @param predicate A callback to authorize the request.
1243
+ * @returns The setters object so that settings can be chained.
1244
+ * @since 2.2.0
1245
+ */
1246
+ authorize(predicate: AuthorizePredicate<TContextData>): OutboxListenerSetters<TContextData>;
1247
+ }
1171
1248
  /**
1172
1249
  * Registry for inbox listeners for different activity types.
1173
1250
  */
@@ -1939,6 +2016,71 @@ interface InboxContext<TContextData> extends Context<TContextData> {
1939
2016
  username: string;
1940
2017
  }, recipients: "followers", options?: ForwardActivityOptions): Promise<void>;
1941
2018
  }
2019
+ /**
2020
+ * A context for outbox listeners.
2021
+ * @since 2.2.0
2022
+ */
2023
+ interface OutboxContext<TContextData> extends Context<TContextData> {
2024
+ /**
2025
+ * The identifier of the actor whose outbox received the POST.
2026
+ * @since 2.2.0
2027
+ */
2028
+ readonly identifier: string;
2029
+ /**
2030
+ * Indicates whether the posted activity has been delivered during the
2031
+ * current outbox listener invocation.
2032
+ * @returns `true` if the posted activity has been delivered; `false`
2033
+ * otherwise.
2034
+ * @since 2.2.0
2035
+ */
2036
+ hasDeliveredActivity(): boolean;
2037
+ /**
2038
+ * Forwards a posted activity to the recipients' inboxes without
2039
+ * re-serializing the original payload. The forwarded activity will be
2040
+ * signed in HTTP Signatures by the forwarder, but its payload will not be
2041
+ * modified, i.e., Linked Data Signatures and Object Integrity Proofs will
2042
+ * not be added. Therefore, if the posted activity is not signed (i.e., it
2043
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2044
+ * recipients probably will not trust the activity.
2045
+ * @param forwarder The forwarder's identifier or the forwarder's username
2046
+ * or the forwarder's key pair(s).
2047
+ * @param recipients The recipients of the activity.
2048
+ * @param options Options for forwarding the activity.
2049
+ * @since 2.2.0
2050
+ */
2051
+ forwardActivity(forwarder: SenderKeyPair | SenderKeyPair[] | {
2052
+ identifier: string;
2053
+ } | {
2054
+ username: string;
2055
+ }, recipients: Recipient | Recipient[], options?: ForwardActivityOptions): Promise<void>;
2056
+ /**
2057
+ * Forwards a posted activity to the recipients' inboxes without
2058
+ * re-serializing the original payload. The forwarded activity will be
2059
+ * signed in HTTP Signatures by the forwarder, but its payload will not be
2060
+ * modified, i.e., Linked Data Signatures and Object Integrity Proofs will
2061
+ * not be added. Therefore, if the posted activity is not signed (i.e., it
2062
+ * has neither Linked Data Signatures nor Object Integrity Proofs), the
2063
+ * recipients probably will not trust the activity.
2064
+ * @param forwarder The forwarder's identifier or the forwarder's username.
2065
+ * @param recipients In this case, it must be `"followers"`.
2066
+ * @param options Options for forwarding the activity.
2067
+ * @since 2.2.0
2068
+ */
2069
+ forwardActivity(forwarder: {
2070
+ identifier: string;
2071
+ } | {
2072
+ username: string;
2073
+ }, recipients: "followers", options?: ForwardActivityOptions): Promise<void>;
2074
+ /**
2075
+ * Creates a new context with the same properties as this one,
2076
+ * but with the given data.
2077
+ * @param data The new data to associate with the context.
2078
+ * @returns A new context with the same properties as this one,
2079
+ * but with the given data.
2080
+ * @since 2.2.0
2081
+ */
2082
+ clone(data: TContextData): OutboxContext<TContextData>;
2083
+ }
1942
2084
  /**
1943
2085
  * A result of parsing an URI.
1944
2086
  */
@@ -2204,5 +2346,11 @@ declare function createInboxContext<TContextData>(args: Partial<InboxContext<TCo
2204
2346
  recipient?: string | null;
2205
2347
  federation: Federation<TContextData>;
2206
2348
  }): InboxContext<TContextData>;
2349
+ declare function createOutboxContext<TContextData>(args: Partial<OutboxContext<TContextData>> & {
2350
+ url?: URL;
2351
+ data: TContextData;
2352
+ identifier: string;
2353
+ federation: Federation<TContextData>;
2354
+ }): OutboxContext<TContextData>;
2207
2355
  //#endregion
2208
- export { createInboxContext, createRequestContext, testDefinitions };
2356
+ export { createInboxContext, createOutboxContext, createRequestContext, testDefinitions };
@@ -1,6 +1,6 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as createRequestContext, t as createInboxContext } from "../context-Juj6bdHC.mjs";
4
+ import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-Dk_tacqz.mjs";
5
5
  import { testDefinitions } from "@fedify/fixture";
6
- export { createInboxContext, createRequestContext, testDefinitions };
6
+ export { createInboxContext, createOutboxContext, createRequestContext, testDefinitions };
@@ -5,9 +5,9 @@ import { t as esm_default } from "../esm-DVILvP5e.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
6
6
  import "../std__assert-Duiq_YC9.mjs";
7
7
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
8
- import { l as verifyRequest } from "../http-RZPxDWq5.mjs";
8
+ import { l as verifyRequest } from "../http-CFmrJbuT.mjs";
9
9
  import { i as rsaPrivateKey2 } from "../keys-BAK-tUlf.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-D7q0-Xef.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-qLB9fFVV.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { UrlError } from "@fedify/vocab-runtime";
13
13
  //#region src/utils/docloader.test.ts
@@ -1,6 +1,6 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_kv_cache = require("../kv-cache-C2gdVgvb.cjs");
4
+ const require_kv_cache = require("../kv-cache-BlXew67e.cjs");
5
5
  exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
6
6
  exports.kvCache = require_kv_cache.kvCache;
package/dist/utils/mod.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-D84Mk0fZ.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-Dgsvz3PC.js";
4
4
  export { getAuthenticatedDocumentLoader, kvCache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "2.2.0-pr.695.16+7a782334",
3
+ "version": "2.2.0-pr.697.17+8d06dbd9",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -144,9 +144,9 @@
144
144
  "uri-template-router": "^1.0.0",
145
145
  "url-template": "^3.1.1",
146
146
  "urlpattern-polyfill": "^10.1.0",
147
- "@fedify/vocab": "2.2.0-pr.695.16+7a782334",
148
- "@fedify/vocab-runtime": "2.2.0-pr.695.16+7a782334",
149
- "@fedify/webfinger": "2.2.0-pr.695.16+7a782334"
147
+ "@fedify/vocab": "2.2.0-pr.697.17+8d06dbd9",
148
+ "@fedify/webfinger": "2.2.0-pr.697.17+8d06dbd9",
149
+ "@fedify/vocab-runtime": "2.2.0-pr.697.17+8d06dbd9"
150
150
  },
151
151
  "devDependencies": {
152
152
  "@std/assert": "npm:@jsr/std__assert@^0.226.0",
@@ -158,7 +158,7 @@
158
158
  "tsx": "^4.19.4",
159
159
  "typescript": "^5.9.2",
160
160
  "wrangler": "^4.17.0",
161
- "@fedify/vocab-tools": "^2.2.0-pr.695.16+7a782334",
161
+ "@fedify/vocab-tools": "^2.2.0-pr.697.17+8d06dbd9",
162
162
  "@fedify/fixture": "2.0.0"
163
163
  },
164
164
  "scripts": {
@@ -1,179 +0,0 @@
1
- import { Temporal } from "@js-temporal/polyfill";
2
- import "urlpattern-polyfill";
3
- globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-vxcWcxQS.mjs";
5
- import { Activity, getTypeId } from "@fedify/vocab";
6
- import { SpanKind, SpanStatusCode, context, propagation, trace } from "@opentelemetry/api";
7
- import { getLogger } from "@logtape/logtape";
8
- //#region src/federation/inbox.ts
9
- var InboxListenerSet = class InboxListenerSet {
10
- #listeners;
11
- constructor() {
12
- this.#listeners = /* @__PURE__ */ new Map();
13
- }
14
- clone() {
15
- const clone = new InboxListenerSet();
16
- clone.#listeners = new Map(this.#listeners);
17
- return clone;
18
- }
19
- add(type, listener) {
20
- if (this.#listeners.has(type)) throw new TypeError("Listener already set for this type.");
21
- this.#listeners.set(type, listener);
22
- }
23
- dispatchWithClass(activity) {
24
- let cls = activity.constructor;
25
- const inboxListeners = this.#listeners;
26
- if (inboxListeners == null) return null;
27
- while (true) {
28
- if (inboxListeners.has(cls)) break;
29
- if (cls === Activity) return null;
30
- cls = globalThis.Object.getPrototypeOf(cls);
31
- }
32
- const listener = inboxListeners.get(cls);
33
- return {
34
- class: cls,
35
- listener
36
- };
37
- }
38
- dispatch(activity) {
39
- return this.dispatchWithClass(activity)?.listener ?? null;
40
- }
41
- };
42
- async function routeActivity({ context: ctx, json, activity, recipient, inboxListeners, inboxContextFactory, inboxErrorHandler, kv, kvPrefixes, queue, span, tracerProvider, idempotencyStrategy }) {
43
- const logger = getLogger([
44
- "fedify",
45
- "federation",
46
- "inbox"
47
- ]);
48
- let cacheKey = null;
49
- if (activity.id != null) {
50
- const inboxContext = inboxContextFactory(recipient, json, activity.id?.href, getTypeId(activity).href);
51
- const strategy = idempotencyStrategy ?? "per-inbox";
52
- let keyString;
53
- if (typeof strategy === "function") keyString = await strategy(inboxContext, activity);
54
- else switch (strategy) {
55
- case "global":
56
- keyString = activity.id.href;
57
- break;
58
- case "per-origin":
59
- keyString = `${ctx.origin}\n${activity.id.href}`;
60
- break;
61
- case "per-inbox":
62
- keyString = `${ctx.origin}\n${activity.id.href}\n${recipient == null ? "sharedInbox" : `inbox\n${recipient}`}`;
63
- break;
64
- default: keyString = `${ctx.origin}\n${activity.id.href}`;
65
- }
66
- if (keyString != null) cacheKey = [...kvPrefixes.activityIdempotence, keyString];
67
- }
68
- if (cacheKey != null) {
69
- if (await kv.get(cacheKey) === true) {
70
- logger.debug("Activity {activityId} has already been processed.", {
71
- activityId: activity.id?.href,
72
- activity: json,
73
- recipient
74
- });
75
- span.setStatus({
76
- code: SpanStatusCode.UNSET,
77
- message: `Activity ${activity.id?.href} has already been processed.`
78
- });
79
- return "alreadyProcessed";
80
- }
81
- }
82
- if (activity.actorId == null) {
83
- logger.error("Missing actor.", { activity: json });
84
- span.setStatus({
85
- code: SpanStatusCode.ERROR,
86
- message: "Missing actor."
87
- });
88
- return "missingActor";
89
- }
90
- span.setAttribute("activitypub.actor.id", activity.actorId.href);
91
- if (queue != null) {
92
- const carrier = {};
93
- propagation.inject(context.active(), carrier);
94
- try {
95
- await queue.enqueue({
96
- type: "inbox",
97
- id: crypto.randomUUID(),
98
- baseUrl: ctx.origin,
99
- activity: json,
100
- identifier: recipient,
101
- attempt: 0,
102
- started: (/* @__PURE__ */ new Date()).toISOString(),
103
- traceContext: carrier
104
- });
105
- } catch (error) {
106
- logger.error("Failed to enqueue the incoming activity {activityId}:\n{error}", {
107
- error,
108
- activityId: activity.id?.href,
109
- activity: json,
110
- recipient
111
- });
112
- span.setStatus({
113
- code: SpanStatusCode.ERROR,
114
- message: `Failed to enqueue the incoming activity ${activity.id?.href}.`
115
- });
116
- throw error;
117
- }
118
- logger.info("Activity {activityId} is enqueued.", {
119
- activityId: activity.id?.href,
120
- activity: json,
121
- recipient
122
- });
123
- return "enqueued";
124
- }
125
- tracerProvider = tracerProvider ?? trace.getTracerProvider();
126
- return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.dispatch_inbox_listener", { kind: SpanKind.INTERNAL }, async (span) => {
127
- const dispatched = inboxListeners?.dispatchWithClass(activity);
128
- if (dispatched == null) {
129
- logger.error("Unsupported activity type:\n{activity}", {
130
- activity: json,
131
- recipient
132
- });
133
- span.setStatus({
134
- code: SpanStatusCode.UNSET,
135
- message: `Unsupported activity type: ${getTypeId(activity).href}`
136
- });
137
- span.end();
138
- return "unsupportedActivity";
139
- }
140
- const { class: cls, listener } = dispatched;
141
- span.updateName(`activitypub.dispatch_inbox_listener ${cls.name}`);
142
- try {
143
- await listener(inboxContextFactory(recipient, json, activity?.id?.href, getTypeId(activity).href), activity);
144
- } catch (error) {
145
- try {
146
- await inboxErrorHandler?.(ctx, error);
147
- } catch (error) {
148
- logger.error("An unexpected error occurred in inbox error handler:\n{error}", {
149
- error,
150
- activityId: activity.id?.href,
151
- activity: json,
152
- recipient
153
- });
154
- }
155
- logger.error("Failed to process the incoming activity {activityId}:\n{error}", {
156
- error,
157
- activityId: activity.id?.href,
158
- activity: json,
159
- recipient
160
- });
161
- span.setStatus({
162
- code: SpanStatusCode.ERROR,
163
- message: String(error)
164
- });
165
- span.end();
166
- return "error";
167
- }
168
- if (cacheKey != null) await kv.set(cacheKey, true, { ttl: Temporal.Duration.from({ days: 1 }) });
169
- logger.info("Activity {activityId} has been processed.", {
170
- activityId: activity.id?.href,
171
- activity: json,
172
- recipient
173
- });
174
- span.end();
175
- return "success";
176
- });
177
- }
178
- //#endregion
179
- export { routeActivity as n, InboxListenerSet as t };