@fedify/fedify 2.4.0-dev.2030 → 2.4.0-dev.2047
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.
- package/dist/{builder-BYJ5otJa.mjs → builder-Cue1kVHU.mjs} +12 -11
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/transformers.test.mjs +1 -1
- package/dist/{compound-proof-BIvUoJxm.mjs → compound-proof-YT4tajyj.mjs} +1 -1
- package/dist/{context-uyRUWoZQ.d.ts → context-BJPHhBmD.d.ts} +100 -2
- package/dist/{context-BeDnDuF3.d.cts → context-Bh_mJfbD.d.cts} +100 -2
- package/dist/{context-CbS35fLr.mjs → context-DG5QeQ8W.mjs} +3 -1
- package/dist/{deno-Vj_9wePq.mjs → deno-Dcj6O4LJ.mjs} +1 -1
- package/dist/{docloader-qUudHZVH.mjs → docloader-BRlNjHlQ.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +3 -3
- package/dist/federation/handler-compound-proof.test.mjs +4 -4
- package/dist/federation/handler.test.mjs +6 -6
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +8 -8
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +3 -3
- package/dist/federation/mod.d.ts +3 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- package/dist/federation/portable.test.d.mts +2 -0
- package/dist/federation/portable.test.mjs +430 -0
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +2 -2
- package/dist/federation/tasks/tasks.test.mjs +3 -3
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +115 -2
- package/dist/{federation-CTnaljmy.cjs → federation-Bdu06LEl.cjs} +324 -26
- package/dist/{http-By8tnmEr.js → http-BmdqHyms.js} +1 -1
- package/dist/{http-B5F1JMh0.cjs → http-CGjvl34X.cjs} +1 -1
- package/dist/{http-D4WPcJUe.mjs → http-CK6kjLnO.mjs} +3 -3
- package/dist/{key-B_Zc5Jbd.mjs → key-CzCAq6D9.mjs} +2 -2
- package/dist/{kv-cache-8K70pjtX.cjs → kv-cache-CvEicbrf.cjs} +1 -1
- package/dist/{kv-cache-BXdT7pJQ.mjs → kv-cache-YATuzCy-.mjs} +1 -1
- package/dist/{kv-cache-BswMKQjC.js → kv-cache-fi_-XZco.js} +1 -1
- package/dist/{ld-B16KUSIQ.mjs → ld-CNWm8mJc.mjs} +3 -3
- package/dist/{metrics-DpQqUAmh.mjs → metrics-CDoBPWjf.mjs} +1 -1
- package/dist/{middleware-BL5HFFVU.mjs → middleware-CF6uz8wa.mjs} +1 -1
- package/dist/{middleware-C7_hqDnl.mjs → middleware-CtFNjIUD.mjs} +326 -28
- package/dist/{middleware-Cxto6Bq2.js → middleware-Drzx-OID.js} +325 -27
- package/dist/{mod-D882_Xsg.d.ts → mod-BofpDIcU.d.ts} +1 -1
- package/dist/{mod-x9W0d0Pk.d.cts → mod-DU8aVzQJ.d.cts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +4 -4
- package/dist/mod.d.ts +4 -4
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/{owner-BIOIhZoM.mjs → owner-B3PgGiJ1.mjs} +2 -2
- package/dist/{owner-D-E0bT2O.js → owner-CMnmv7S9.js} +16 -3
- package/dist/{owner-WUYke16i.cjs → owner-Hurn_ocn.cjs} +16 -3
- package/dist/{proof-BVxJu5vv.mjs → proof-fKycdssC.mjs} +18 -5
- package/dist/{send-Cr5FJ7iu.mjs → send-BqBILxYE.mjs} +3 -3
- package/dist/sig/compound-proof-discovery.test.mjs +1 -1
- package/dist/sig/compound-proof-producer.test.mjs +1 -1
- package/dist/sig/compound-proof-verification.test.mjs +2 -2
- package/dist/sig/compound-proof.test.mjs +2 -2
- package/dist/sig/http.test.mjs +2 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +2 -2
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/proof.test.mjs +208 -1
- package/dist/{temporal-CCf0lZV3.mjs → temporal-SUiLJ0Co.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +99 -1
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-hbky2gMN.mjs → testing-By1YYsIK.mjs} +1 -1
- package/dist/utils/docloader.test.mjs +2 -2
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +7 -7
package/dist/sig/proof.test.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
+
import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
|
|
4
5
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
5
6
|
import { t as assertFalse } from "../assert_false-CPdRnc3E.mjs";
|
|
6
7
|
import { t as assertGreaterOrEqual } from "../assert_greater_or_equal-BlafOF4-.mjs";
|
|
@@ -8,9 +9,11 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
|
|
|
8
9
|
import "../std__assert-DvMDRPes.mjs";
|
|
9
10
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
10
11
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
12
|
+
import { l as verifyRequest } from "../http-CK6kjLnO.mjs";
|
|
11
13
|
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
14
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-BRlNjHlQ.mjs";
|
|
12
15
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
13
|
-
import { a as verifyObject, c as verifyProof, n as hasProofLike, o as verifyPortableObjectProof, r as signObject, t as createProof } from "../proof-
|
|
16
|
+
import { a as verifyObject, c as verifyProof, n as hasProofLike, o as verifyPortableObjectProof, r as signObject, t as createProof } from "../proof-fKycdssC.mjs";
|
|
14
17
|
import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
|
|
15
18
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
16
19
|
import { decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
|
|
@@ -1613,6 +1616,80 @@ test("verifyObject() hydrates pending proof references", async () => {
|
|
|
1613
1616
|
assertEquals(proofFetches, 1);
|
|
1614
1617
|
assertInstanceOf(verified, Note);
|
|
1615
1618
|
});
|
|
1619
|
+
test("verifyObject() hydrates portable proof references with gateway hints", async () => {
|
|
1620
|
+
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
1621
|
+
const method = did.substring(8);
|
|
1622
|
+
const keyId = new URL(`${did}#${method}`);
|
|
1623
|
+
const proofId = `ap://did:key:${method}/proofs/1`;
|
|
1624
|
+
const proofReference = `${proofId}?@gateway=https%3A%2F%2Fgateway.example`;
|
|
1625
|
+
const signed = await signPortableJsonLd({
|
|
1626
|
+
"@context": portableContext,
|
|
1627
|
+
id: `ap://did:key:${method}/objects/1`,
|
|
1628
|
+
type: "Note",
|
|
1629
|
+
attributedTo: `ap://did:key:${method}/actor`,
|
|
1630
|
+
content: "Portable note with a hinted proof reference"
|
|
1631
|
+
}, {
|
|
1632
|
+
verificationMethod: keyId,
|
|
1633
|
+
proofOptions: { id: proofId }
|
|
1634
|
+
});
|
|
1635
|
+
const rawProof = signed.proof;
|
|
1636
|
+
const referencedJsonLd = { ...signed };
|
|
1637
|
+
delete referencedJsonLd.proof;
|
|
1638
|
+
referencedJsonLd["https://w3id.org/security#proof"] = [{ "@graph": [rawProof] }, { "@graph": [{ "@id": proofReference }] }];
|
|
1639
|
+
const fetched = [];
|
|
1640
|
+
const verified = await verifyObject(Note, referencedJsonLd, {
|
|
1641
|
+
documentLoader(url) {
|
|
1642
|
+
fetched.push(url);
|
|
1643
|
+
return Promise.resolve({
|
|
1644
|
+
contextUrl: null,
|
|
1645
|
+
document: structuredClone(rawProof),
|
|
1646
|
+
documentUrl: url
|
|
1647
|
+
});
|
|
1648
|
+
},
|
|
1649
|
+
contextLoader: mockDocumentLoader
|
|
1650
|
+
});
|
|
1651
|
+
assertEquals(fetched, [formatIri(parseIri(proofReference))]);
|
|
1652
|
+
assertInstanceOf(verified, Note);
|
|
1653
|
+
});
|
|
1654
|
+
test("verifyObject() rejects portable proof references it cannot dereference", async () => {
|
|
1655
|
+
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
1656
|
+
const method = did.substring(8);
|
|
1657
|
+
const keyId = new URL(`${did}#${method}`);
|
|
1658
|
+
const proofUrl = `ap://did:key:${method}/proofs/2`;
|
|
1659
|
+
const signed = await signPortableJsonLd({
|
|
1660
|
+
"@context": portableContext,
|
|
1661
|
+
id: `ap://did:key:${method}/objects/1`,
|
|
1662
|
+
type: "Note",
|
|
1663
|
+
attributedTo: `ap://did:key:${method}/actor`,
|
|
1664
|
+
content: "Portable note with an extra referenced proof"
|
|
1665
|
+
}, { verificationMethod: keyId });
|
|
1666
|
+
const rawProof = signed.proof;
|
|
1667
|
+
const withProofs = (proofs) => {
|
|
1668
|
+
const referencedJsonLd = { ...signed };
|
|
1669
|
+
delete referencedJsonLd.proof;
|
|
1670
|
+
referencedJsonLd["https://w3id.org/security#proof"] = proofs;
|
|
1671
|
+
return referencedJsonLd;
|
|
1672
|
+
};
|
|
1673
|
+
const embedded = { "@graph": [rawProof] };
|
|
1674
|
+
const referenced = { "@graph": [{ "@id": proofUrl }] };
|
|
1675
|
+
for (const [id, referencedJsonLd] of [
|
|
1676
|
+
[`ap://did:key:${method}/proofs/3`, withProofs([embedded, referenced])],
|
|
1677
|
+
[`ap://did:key:z6MkhaXgBZDvotDkL5257faiztiGiC2QtKLGpbnnEGta2doK/proofs/2`, withProofs([embedded, referenced])],
|
|
1678
|
+
[`ap://did:key:${method}/proofs/3`, withProofs([referenced, embedded])]
|
|
1679
|
+
]) assertEquals(await verifyObject(Note, referencedJsonLd, {
|
|
1680
|
+
documentLoader(url) {
|
|
1681
|
+
return Promise.resolve({
|
|
1682
|
+
contextUrl: null,
|
|
1683
|
+
document: {
|
|
1684
|
+
...rawProof,
|
|
1685
|
+
id
|
|
1686
|
+
},
|
|
1687
|
+
documentUrl: url
|
|
1688
|
+
});
|
|
1689
|
+
},
|
|
1690
|
+
contextLoader: mockDocumentLoader
|
|
1691
|
+
}), null);
|
|
1692
|
+
});
|
|
1616
1693
|
test("verifyObject() accepts multiple portable attributions from the same did:key origin", async () => {
|
|
1617
1694
|
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
1618
1695
|
const method = did.substring(8);
|
|
@@ -1818,5 +1895,135 @@ test("verifyObject() rejects a key that claims a forged controller", async () =>
|
|
|
1818
1895
|
contextLoader: mockDocumentLoader
|
|
1819
1896
|
}), null);
|
|
1820
1897
|
});
|
|
1898
|
+
test("verifyPortableObjectProof() verifies objects fetched through gateways", async (t) => {
|
|
1899
|
+
const objectId = `ap://${portableDid}/objects/gateway`;
|
|
1900
|
+
const gatewayUrl = `https://gateway.example/.well-known/apgateway/${portableDid}/objects/gateway`;
|
|
1901
|
+
const signedNote = await signPortableJsonLd({
|
|
1902
|
+
"@context": portableContext,
|
|
1903
|
+
id: objectId,
|
|
1904
|
+
type: "Note",
|
|
1905
|
+
attributedTo: `ap://${portableDid}/actor`,
|
|
1906
|
+
content: "Hello from a gateway"
|
|
1907
|
+
});
|
|
1908
|
+
const getObject = async (document, object = objectId, url = gatewayUrl) => {
|
|
1909
|
+
return await (await Create.fromJsonLd({
|
|
1910
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
1911
|
+
type: "Create",
|
|
1912
|
+
id: `ap://${portableDid}/activities/1`,
|
|
1913
|
+
object
|
|
1914
|
+
}, { contextLoader: mockDocumentLoader })).getObject({
|
|
1915
|
+
documentLoader: async (requestUrl) => {
|
|
1916
|
+
if (requestUrl !== url) throw new Error(`Unexpected URL: ${requestUrl}`);
|
|
1917
|
+
return {
|
|
1918
|
+
contextUrl: null,
|
|
1919
|
+
documentUrl: requestUrl,
|
|
1920
|
+
document
|
|
1921
|
+
};
|
|
1922
|
+
},
|
|
1923
|
+
contextLoader: mockDocumentLoader,
|
|
1924
|
+
gateways: ["https://gateway.example"],
|
|
1925
|
+
verifyPortableObject: verifyPortableObjectProof
|
|
1926
|
+
});
|
|
1927
|
+
};
|
|
1928
|
+
await t.step("a properly signed object", async () => {
|
|
1929
|
+
const object = await getObject(signedNote);
|
|
1930
|
+
assertInstanceOf(object, Note);
|
|
1931
|
+
assertEquals(object.content, "Hello from a gateway");
|
|
1932
|
+
});
|
|
1933
|
+
await t.step("a tampered object", async () => {
|
|
1934
|
+
assertEquals(await getObject({
|
|
1935
|
+
...signedNote,
|
|
1936
|
+
content: "Tampered"
|
|
1937
|
+
}), null);
|
|
1938
|
+
});
|
|
1939
|
+
await t.step("an object without a proof", async () => {
|
|
1940
|
+
const { proof: _, ...unsigned } = signedNote;
|
|
1941
|
+
assertEquals(await getObject(unsigned), null);
|
|
1942
|
+
});
|
|
1943
|
+
await t.step("an object without an ID", async () => {
|
|
1944
|
+
const withoutId = await signPortableJsonLd({
|
|
1945
|
+
"@context": portableContext,
|
|
1946
|
+
type: "Note",
|
|
1947
|
+
content: "Hello from a gateway"
|
|
1948
|
+
});
|
|
1949
|
+
assertEquals(await getObject(withoutId), null);
|
|
1950
|
+
});
|
|
1951
|
+
await t.step("another object of the same DID", async () => {
|
|
1952
|
+
assertEquals(await getObject(signedNote, `ap://${portableDid}/objects/other`, `https://gateway.example/.well-known/apgateway/${portableDid}/objects/other`), null);
|
|
1953
|
+
});
|
|
1954
|
+
await t.step("an object signed by another DID", async () => {
|
|
1955
|
+
const otherDid = await exportDidKey(await crypto.subtle.importKey("jwk", {
|
|
1956
|
+
kty: "OKP",
|
|
1957
|
+
crv: "Ed25519",
|
|
1958
|
+
x: "sA2Nk45_dz1RVlqtNqYj9TRPf10ZYPnPPo4SYg6igQ8",
|
|
1959
|
+
key_ops: ["verify"],
|
|
1960
|
+
ext: true
|
|
1961
|
+
}, "Ed25519", true, ["verify"]));
|
|
1962
|
+
const otherObjectId = `ap://${otherDid}/objects/gateway`;
|
|
1963
|
+
const otherGatewayUrl = `https://gateway.example/.well-known/apgateway/${otherDid}/objects/gateway`;
|
|
1964
|
+
const spoofed = await signPortableJsonLd({
|
|
1965
|
+
"@context": portableContext,
|
|
1966
|
+
id: otherObjectId,
|
|
1967
|
+
type: "Note",
|
|
1968
|
+
content: "Spoofed"
|
|
1969
|
+
});
|
|
1970
|
+
assertEquals(await getObject(spoofed, otherObjectId, otherGatewayUrl), null);
|
|
1971
|
+
const forged = await signPortableJsonLd({
|
|
1972
|
+
"@context": portableContext,
|
|
1973
|
+
id: objectId,
|
|
1974
|
+
type: "Note",
|
|
1975
|
+
content: "Forged"
|
|
1976
|
+
}, { privateKey: fep8b32TestVectorPrivateKey });
|
|
1977
|
+
assertEquals(await getObject(forged), null);
|
|
1978
|
+
});
|
|
1979
|
+
});
|
|
1980
|
+
test("getAuthenticatedDocumentLoader() signs portable object requests to gateways", {
|
|
1981
|
+
sanitizeResources: false,
|
|
1982
|
+
sanitizeOps: false
|
|
1983
|
+
}, async () => {
|
|
1984
|
+
const objectId = `ap://${portableDid}/objects/private`;
|
|
1985
|
+
const signedNote = await signPortableJsonLd({
|
|
1986
|
+
"@context": portableContext,
|
|
1987
|
+
id: objectId,
|
|
1988
|
+
type: "Note",
|
|
1989
|
+
attributedTo: `ap://${portableDid}/actor`,
|
|
1990
|
+
content: "Followers only"
|
|
1991
|
+
});
|
|
1992
|
+
esm_default.spyGlobal();
|
|
1993
|
+
let signed = false;
|
|
1994
|
+
let accept = null;
|
|
1995
|
+
esm_default.get(`https://example.com/.well-known/apgateway/${portableDid}/objects/private`, async (cl) => {
|
|
1996
|
+
accept = cl.request.headers.get("Accept");
|
|
1997
|
+
signed = await verifyRequest(cl.request, {
|
|
1998
|
+
documentLoader: mockDocumentLoader,
|
|
1999
|
+
contextLoader: mockDocumentLoader,
|
|
2000
|
+
currentTime: Temporal.Now.instant()
|
|
2001
|
+
}) != null;
|
|
2002
|
+
if (!signed) return new Response(null, { status: 401 });
|
|
2003
|
+
return new Response(JSON.stringify(signedNote), { headers: { "Content-Type": "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" } });
|
|
2004
|
+
});
|
|
2005
|
+
try {
|
|
2006
|
+
const object = await (await Create.fromJsonLd({
|
|
2007
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
2008
|
+
type: "Create",
|
|
2009
|
+
id: `ap://${portableDid}/activities/1`,
|
|
2010
|
+
object: objectId
|
|
2011
|
+
}, { contextLoader: mockDocumentLoader })).getObject({
|
|
2012
|
+
documentLoader: getAuthenticatedDocumentLoader({
|
|
2013
|
+
keyId: new URL("https://example.com/key2"),
|
|
2014
|
+
privateKey: rsaPrivateKey2
|
|
2015
|
+
}),
|
|
2016
|
+
contextLoader: mockDocumentLoader,
|
|
2017
|
+
gateways: ["https://example.com"],
|
|
2018
|
+
verifyPortableObject: verifyPortableObjectProof
|
|
2019
|
+
});
|
|
2020
|
+
assertInstanceOf(object, Note);
|
|
2021
|
+
assertEquals(object.content, "Followers only");
|
|
2022
|
+
assert(signed);
|
|
2023
|
+
assertEquals(accept, "application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"");
|
|
2024
|
+
} finally {
|
|
2025
|
+
esm_default.hardReset();
|
|
2026
|
+
}
|
|
2027
|
+
});
|
|
1821
2028
|
//#endregion
|
|
1822
2029
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { c as getNormalizationContextLoader } from "./ld-
|
|
4
|
+
import { c as getNormalizationContextLoader } from "./ld-CNWm8mJc.mjs";
|
|
5
5
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
6
6
|
//#region src/federation/temporal.ts
|
|
7
7
|
function isPlainObject(value) {
|
package/dist/testing/kv.test.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
|
|
|
6
6
|
import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
|
|
7
7
|
import { n as baseOptions, o as stringSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
|
|
8
8
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
9
|
-
import { o as createFederation } from "../middleware-
|
|
9
|
+
import { o as createFederation } from "../middleware-CtFNjIUD.mjs";
|
|
10
10
|
//#region src/testing/kv.test.ts
|
|
11
11
|
test("ManualClockKvStore keeps an entry at its exact expiration instant", async () => {
|
|
12
12
|
const kv = new ManualClockKvStore();
|
package/dist/testing/mod.d.mts
CHANGED
|
@@ -2700,6 +2700,35 @@ interface Context<TContextData> {
|
|
|
2700
2700
|
* @since 0.7.0
|
|
2701
2701
|
*/
|
|
2702
2702
|
getObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>): URL;
|
|
2703
|
+
/**
|
|
2704
|
+
* Builds the [FEP-ef61] portable ID of an object with the given class and
|
|
2705
|
+
* values under the given DID authority.
|
|
2706
|
+
*
|
|
2707
|
+
* The path is the same as the one {@link Context.getObjectUri} builds from
|
|
2708
|
+
* the object dispatcher's path, but the result is an `ap+ef61:` URI whose
|
|
2709
|
+
* authority is the DID, e.g., `ap+ef61://did:key:z6Mk.../notes/123`.
|
|
2710
|
+
* Such an object can be served through the FEP-ef61 gateway endpoint,
|
|
2711
|
+
* `/.well-known/apgateway/did:key:z6Mk.../notes/123`, by the same object
|
|
2712
|
+
* dispatcher.
|
|
2713
|
+
*
|
|
2714
|
+
* The returned `URL` keeps the DID authority percent-encoded, because
|
|
2715
|
+
* the `URL` class cannot represent the canonical form. Use `formatIri()`
|
|
2716
|
+
* from `@fedify/vocab-runtime` to get the canonical string, e.g.,
|
|
2717
|
+
* `ap+ef61://did:key:z6Mk.../notes/123`.
|
|
2718
|
+
*
|
|
2719
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2720
|
+
*
|
|
2721
|
+
* @param cls The class of the object.
|
|
2722
|
+
* @param values The values to pass to the object dispatcher.
|
|
2723
|
+
* @param authority The DID that controls the object, e.g.,
|
|
2724
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
2725
|
+
* a path, query, or fragment.
|
|
2726
|
+
* @returns The object's portable ID.
|
|
2727
|
+
* @throws {RouterError} If no object dispatcher is available for the class.
|
|
2728
|
+
* @throws {TypeError} If values are invalid or the authority is not a DID.
|
|
2729
|
+
* @since 2.4.0
|
|
2730
|
+
*/
|
|
2731
|
+
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority: string): URL;
|
|
2703
2732
|
/**
|
|
2704
2733
|
* Builds the URI of an actor's outbox with the given identifier.
|
|
2705
2734
|
* @param identifier The actor's identifier.
|
|
@@ -2846,7 +2875,13 @@ interface Context<TContextData> {
|
|
|
2846
2875
|
* ```
|
|
2847
2876
|
*
|
|
2848
2877
|
* It's almost the same as the {@link lookupObject} function, but it uses
|
|
2849
|
-
* the context's document loader and context loader by default.
|
|
2878
|
+
* the context's document loader and context loader by default. It also
|
|
2879
|
+
* uses `verifyPortableObjectProof()` as the `verifyPortableObject`
|
|
2880
|
+
* option by default (since 2.4.0), so [FEP-ef61] portable objects,
|
|
2881
|
+
* including portable actors found through WebFinger, are looked up through
|
|
2882
|
+
* their gateways and returned only if they have valid proofs.
|
|
2883
|
+
*
|
|
2884
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2850
2885
|
*
|
|
2851
2886
|
* @param identifier The URI or fediverse handle to look up.
|
|
2852
2887
|
* @param options Lookup options.
|
|
@@ -3020,6 +3055,29 @@ interface Context<TContextData> {
|
|
|
3020
3055
|
*/
|
|
3021
3056
|
getCollectionUri<TParam extends Record<string, string>>(name: string | symbol, values: TParam): URL;
|
|
3022
3057
|
}
|
|
3058
|
+
/**
|
|
3059
|
+
* Information about an [FEP-ef61] portable object requested through
|
|
3060
|
+
* the gateway endpoint. See {@link RequestContext.portableRequest}.
|
|
3061
|
+
*
|
|
3062
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3063
|
+
* @since 2.4.0
|
|
3064
|
+
*/
|
|
3065
|
+
interface PortableRequest {
|
|
3066
|
+
/**
|
|
3067
|
+
* The DID authority of the requested portable object, e.g.,
|
|
3068
|
+
* `did:key:z6Mk...`. It comes from the request path, so it is not
|
|
3069
|
+
* evidence that this server hosts objects for the DID.
|
|
3070
|
+
*/
|
|
3071
|
+
readonly authority: string;
|
|
3072
|
+
/**
|
|
3073
|
+
* The ID of the requested portable object, e.g.,
|
|
3074
|
+
* `ap+ef61://did:key:z6Mk.../notes/123`, without a query. Like other
|
|
3075
|
+
* portable IDs, the `URL` keeps the DID authority percent-encoded; use
|
|
3076
|
+
* `formatIri()` from `@fedify/vocab-runtime` to get the canonical string.
|
|
3077
|
+
* Each access returns a new `URL` instance.
|
|
3078
|
+
*/
|
|
3079
|
+
readonly id: URL;
|
|
3080
|
+
}
|
|
3023
3081
|
/**
|
|
3024
3082
|
* Options for {@link RequestContext.getActor}.
|
|
3025
3083
|
* @since 2.2.0
|
|
@@ -3045,6 +3103,46 @@ interface RequestContext<TContextData> extends Context<TContextData> {
|
|
|
3045
3103
|
* The URL of the request.
|
|
3046
3104
|
*/
|
|
3047
3105
|
readonly url: URL;
|
|
3106
|
+
/**
|
|
3107
|
+
* Information about the [FEP-ef61] portable object requested through
|
|
3108
|
+
* the gateway endpoint, e.g.,
|
|
3109
|
+
* `GET /.well-known/apgateway/did:key:z6Mk.../notes/123`. It is
|
|
3110
|
+
* `undefined` for ordinary requests.
|
|
3111
|
+
*
|
|
3112
|
+
* The authority comes from the request path, so it is not evidence that
|
|
3113
|
+
* this server hosts objects for the DID. An object dispatcher has to check
|
|
3114
|
+
* that by itself.
|
|
3115
|
+
*
|
|
3116
|
+
* It describes the incoming request, so it stays the same in contexts
|
|
3117
|
+
* derived from this one, e.g., by {@link RequestContext.getObject}.
|
|
3118
|
+
*
|
|
3119
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3120
|
+
* @since 2.4.0
|
|
3121
|
+
*/
|
|
3122
|
+
readonly portableRequest?: PortableRequest;
|
|
3123
|
+
/**
|
|
3124
|
+
* Builds the [FEP-ef61] portable ID of an object with the given class and
|
|
3125
|
+
* values. It works the same as {@link Context.getPortableObjectUri}, except
|
|
3126
|
+
* that the authority can be omitted while handling a portable gateway
|
|
3127
|
+
* request. In that case, the DID in {@link RequestContext.portableRequest}
|
|
3128
|
+
* is used.
|
|
3129
|
+
*
|
|
3130
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
3131
|
+
*
|
|
3132
|
+
* @param cls The class of the object.
|
|
3133
|
+
* @param values The values to pass to the object dispatcher.
|
|
3134
|
+
* @param authority The DID that controls the object, e.g.,
|
|
3135
|
+
* `did:key:z6Mk...`. It must be a bare DID, without
|
|
3136
|
+
* a path, query, or fragment. Defaults to the DID of
|
|
3137
|
+
* the requested portable object.
|
|
3138
|
+
* @returns The object's portable ID.
|
|
3139
|
+
* @throws {RouterError} If no object dispatcher is available for the class.
|
|
3140
|
+
* @throws {TypeError} If values are invalid, the authority is not a DID, or
|
|
3141
|
+
* the authority is omitted outside a portable gateway
|
|
3142
|
+
* request.
|
|
3143
|
+
* @since 2.4.0
|
|
3144
|
+
*/
|
|
3145
|
+
getPortableObjectUri<TObject extends Object$1>(cls: ConstructorWithTypeId<TObject>, values: Record<string, string>, authority?: string): URL;
|
|
3048
3146
|
/**
|
|
3049
3147
|
* Creates a new context with the same properties as this one,
|
|
3050
3148
|
* but with the given data.
|
package/dist/testing/mod.mjs
CHANGED
|
@@ -2,8 +2,8 @@ import "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { r as testDefinitions } from "../dist-BQvArojP.mjs";
|
|
5
|
-
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-
|
|
5
|
+
import { n as createOutboxContext, r as createRequestContext, t as createInboxContext } from "../context-DG5QeQ8W.mjs";
|
|
6
6
|
import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
|
|
7
7
|
import { a as numberSchema, i as makeSchema, n as baseOptions, o as stringSchema, r as envelopeSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
|
|
8
|
-
import "../testing-
|
|
8
|
+
import "../testing-By1YYsIK.mjs";
|
|
9
9
|
export { ManualClockKvStore, MockQueue, baseOptions, createInboxContext, createOutboxContext, createRequestContext, envelopeSchema, makeSchema, numberSchema, stringSchema, testDefinitions };
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import "./dist-BQvArojP.mjs";
|
|
5
|
-
import "./context-
|
|
5
|
+
import "./context-DG5QeQ8W.mjs";
|
|
6
6
|
import "./kv-DBRWVx3Q.mjs";
|
|
7
7
|
import "./tasks-dbCShlCb.mjs";
|
|
8
8
|
export {};
|
|
@@ -5,9 +5,9 @@ import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
|
|
|
5
5
|
import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
|
|
6
6
|
import "../std__assert-DvMDRPes.mjs";
|
|
7
7
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
8
|
-
import { l as verifyRequest } from "../http-
|
|
8
|
+
import { l as verifyRequest } from "../http-CK6kjLnO.mjs";
|
|
9
9
|
import { i as rsaPrivateKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
10
|
-
import { t as getAuthenticatedDocumentLoader } from "../docloader-
|
|
10
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-BRlNjHlQ.mjs";
|
|
11
11
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
12
12
|
import { FetchError, UrlError } from "@fedify/vocab-runtime";
|
|
13
13
|
//#region src/utils/docloader.test.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as kvCache, t as MockKvStore } from "../kv-cache-
|
|
4
|
+
import { n as kvCache, t as MockKvStore } from "../kv-cache-YATuzCy-.mjs";
|
|
5
5
|
import { deepStrictEqual, throws } from "node:assert";
|
|
6
6
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
7
7
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
package/dist/utils/mod.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const require_kv_cache = require("../kv-cache-
|
|
3
|
+
const require_kv_cache = require("../kv-cache-CvEicbrf.cjs");
|
|
4
4
|
exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
|
|
5
5
|
exports.kvCache = require_kv_cache.kvCache;
|
package/dist/utils/mod.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-
|
|
3
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-fi_-XZco.js";
|
|
4
4
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/fedify",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.2047+140b94db",
|
|
4
4
|
"description": "An ActivityPub server framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ActivityPub",
|
|
@@ -151,15 +151,15 @@
|
|
|
151
151
|
"structured-field-values": "^2.0.4",
|
|
152
152
|
"temporal-polyfill": "^1.0.1",
|
|
153
153
|
"urlpattern-polyfill": "^10.1.0",
|
|
154
|
-
"@fedify/
|
|
155
|
-
"@fedify/
|
|
156
|
-
"@fedify/
|
|
157
|
-
"@fedify/
|
|
154
|
+
"@fedify/uri-template": "2.4.0-dev.2047+140b94db",
|
|
155
|
+
"@fedify/vocab": "2.4.0-dev.2047+140b94db",
|
|
156
|
+
"@fedify/vocab-runtime": "2.4.0-dev.2047+140b94db",
|
|
157
|
+
"@fedify/webfinger": "2.4.0-dev.2047+140b94db"
|
|
158
158
|
},
|
|
159
159
|
"devDependencies": {
|
|
160
160
|
"@std/assert": "npm:@jsr/std__assert@^0.226.0",
|
|
161
161
|
"@std/path": "npm:@jsr/std__path@^1.0.6",
|
|
162
|
-
"@types/node": "^24.2
|
|
162
|
+
"@types/node": "^24.12.2",
|
|
163
163
|
"fetch-mock": "^12.5.4",
|
|
164
164
|
"miniflare": "^4.20250523.0",
|
|
165
165
|
"tsdown": "^0.22.0",
|
|
@@ -167,7 +167,7 @@
|
|
|
167
167
|
"typescript": "^6.0.0",
|
|
168
168
|
"wrangler": "^4.17.0",
|
|
169
169
|
"@fedify/fixture": "2.0.0",
|
|
170
|
-
"@fedify/vocab-tools": "^2.4.0-dev.
|
|
170
|
+
"@fedify/vocab-tools": "^2.4.0-dev.2047+140b94db"
|
|
171
171
|
},
|
|
172
172
|
"scripts": {
|
|
173
173
|
"build:self": "tsdown",
|