@fedify/fedify 2.4.0-dev.2065 → 2.4.0-dev.2071
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-CMkrnYbY.mjs → builder-DVQ0yhKJ.mjs} +6 -2
- 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-Dj3DCsoj.mjs → compound-proof-KmXDfWFp.mjs} +1 -1
- package/dist/{context-b36TpPoG.d.cts → context-DijrgHDe.d.cts} +45 -2
- package/dist/{context-D_gg4M0n.d.ts → context-DsB9kF6q.d.ts} +45 -2
- package/dist/{deno-BuRFI7wk.mjs → deno-B-NtYZVW.mjs} +1 -1
- package/dist/{docloader-_aSNLA90.mjs → docloader-C6yOVoaF.mjs} +2 -2
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +4 -4
- package/dist/federation/handler-compound-proof.test.mjs +3 -3
- package/dist/federation/handler.test.mjs +5 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- 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 +6 -6
- package/dist/federation/portable-gateway-keys.test.d.mts +2 -0
- package/dist/federation/portable-gateway-keys.test.mjs +363 -0
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +3 -3
- package/dist/federation/tasks/enqueue.test.mjs +1 -1
- package/dist/federation/tasks/tasks.test.mjs +2 -2
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +1 -1
- package/dist/{federation-Coi_bg12.cjs → federation-CUiHc7dP.cjs} +182 -76
- package/dist/http-BoWBwC0g.js +5087 -0
- package/dist/{http-BGShIsd6.cjs → http-CuLWIJdf.cjs} +2684 -48
- package/dist/{http-f1qaBtOh.mjs → http-DKWi8RjI.mjs} +20 -5
- package/dist/{http-65PYi9jY.d.ts → http-n2v6DPxu.d.ts} +52 -2
- package/dist/{http-CP-7OdSq.d.cts → http-xlG-jRdB.d.cts} +52 -2
- package/dist/{key-BxHsA1s9.mjs → key-lfcx_NaE.mjs} +147 -7
- package/dist/{kv-cache-Cgj-kpQS.js → kv-cache-BdnmnAVc.js} +1 -1
- package/dist/{kv-cache-CY6pDNoS.cjs → kv-cache-DE8kSNQU.cjs} +1 -1
- package/dist/{kv-cache-C9IY-FMN.mjs → kv-cache-d8EjO29d.mjs} +1 -1
- package/dist/{ld-CqJq5erX.mjs → ld-jyjdrWjG.mjs} +3 -3
- package/dist/{metrics-DOqknlZd.mjs → metrics-B5Rei-HC.mjs} +1 -1
- package/dist/{middleware-1h_LgwXC.js → middleware-CAObohey.js} +149 -43
- package/dist/{middleware-s-AZzx4r.mjs → middleware-CPx4ZWwt.mjs} +155 -53
- package/dist/{middleware-VOCZN3SO.mjs → middleware-CdVnCDXD.mjs} +1 -1
- package/dist/{mod-Dhm7SqyE.d.ts → mod-C9WSpZWm.d.ts} +1 -1
- package/dist/{mod-C0BYc0OU.d.ts → mod-CVZrXSdm.d.ts} +1 -1
- package/dist/{mod-BhMvsgdF.d.ts → mod-DMkflQdF.d.ts} +1 -1
- package/dist/{mod-Bfenkg_c.d.cts → mod-DTAaBwiY.d.cts} +1 -1
- package/dist/{mod-pLbeNwcC.d.cts → mod-HDSvS-ww.d.cts} +1 -1
- package/dist/{mod-CyiSjRkk.d.cts → mod-xGFCHqq_.d.cts} +1 -1
- package/dist/mod.cjs +18 -18
- package/dist/mod.d.cts +7 -7
- package/dist/mod.d.ts +7 -7
- package/dist/mod.js +5 -5
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/owner-1TFakcTF.js +215 -0
- package/dist/owner-BXufwAzm.cjs +225 -0
- package/dist/{owner-D_F22lfM.mjs → owner-ByqNQVaa.mjs} +45 -2
- package/dist/portable-key-Cw_ow5vn.mjs +194 -0
- package/dist/{proof-B03JXhrk.mjs → proof-B6gwdhN5.mjs} +5 -5
- package/dist/{send-NNkfKtVN.mjs → send-DsK7xevO.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 +3 -3
- 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 +16 -16
- package/dist/sig/mod.d.cts +2 -2
- package/dist/sig/mod.d.ts +2 -2
- package/dist/sig/mod.js +3 -3
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +3 -3
- package/dist/sig/portable-key.test.d.mts +2 -0
- package/dist/sig/portable-key.test.mjs +275 -0
- package/dist/sig/proof.test.mjs +4 -4
- package/dist/{sig-Bb20Pyrd.js → sig-BR_Z6mpY.js} +2 -2
- package/dist/{sig-B1E2uyhQ.cjs → sig-TTn9wYrE.cjs} +4 -4
- package/dist/{temporal-VVVSuruq.mjs → temporal-Bw5jtrBY.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +43 -0
- 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.d.cts +1 -1
- package/dist/utils/mod.d.ts +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +6 -6
- package/dist/http-z5n7chWw.js +0 -2647
- package/dist/owner-BLBWXCNt.js +0 -2276
- package/dist/owner-D8ZpRusc.cjs +0 -2446
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import "temporal-polyfill";
|
|
2
|
+
import "urlpattern-polyfill";
|
|
3
|
+
globalThis.addEventListener = () => {};
|
|
4
|
+
import { r as fetchKey } from "../key-lfcx_NaE.mjs";
|
|
5
|
+
import { l as verifyRequest, s as signRequest } from "../http-DKWi8RjI.mjs";
|
|
6
|
+
import { c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
|
|
7
|
+
import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-ByqNQVaa.mjs";
|
|
8
|
+
import { Create, CryptographicKey, Multikey, Person } from "@fedify/vocab";
|
|
9
|
+
import { test } from "@fedify/fixture";
|
|
10
|
+
import { FetchError, encodeMultibase, exportDidKey, parseIri, preloadedContexts } from "@fedify/vocab-runtime";
|
|
11
|
+
import serialize from "json-canon";
|
|
12
|
+
import { deepStrictEqual, ok, strictEqual } from "node:assert/strict";
|
|
13
|
+
//#region src/sig/portable-key.test.ts
|
|
14
|
+
const did = await exportDidKey(ed25519PublicKey.publicKey);
|
|
15
|
+
const didKeyId = `${did}#${did.slice(8)}`;
|
|
16
|
+
const otherKeyPair = await crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"]);
|
|
17
|
+
const otherDid = await exportDidKey(otherKeyPair.publicKey);
|
|
18
|
+
const actorId = `ap+ef61://${did}/actor`;
|
|
19
|
+
const gw1 = "https://gw1.example";
|
|
20
|
+
const gw2 = "https://gw2.example";
|
|
21
|
+
function compatibleId(gateway, id = actorId) {
|
|
22
|
+
return `${gateway}/.well-known/apgateway/${id.replace(/^ap\+ef61:\/\//, "")}`;
|
|
23
|
+
}
|
|
24
|
+
const keyId = new URL(`${compatibleId(gw1)}#main-key`);
|
|
25
|
+
const gatewayPublicKey = rsaPublicKey2.publicKey;
|
|
26
|
+
const contextLoader = (url) => {
|
|
27
|
+
const document = preloadedContexts[url];
|
|
28
|
+
if (document == null) return Promise.reject(/* @__PURE__ */ new Error(`No context: ${url}`));
|
|
29
|
+
return Promise.resolve({
|
|
30
|
+
contextUrl: null,
|
|
31
|
+
documentUrl: url,
|
|
32
|
+
document
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
function createLoader(responses) {
|
|
36
|
+
const fetched = [];
|
|
37
|
+
const loader = (url) => {
|
|
38
|
+
fetched.push(url);
|
|
39
|
+
const document = responses[url.replace(/#.*$/, "")];
|
|
40
|
+
if (document == null) return Promise.reject(new FetchError(url, "HTTP 404", new Response(null, { status: 404 })));
|
|
41
|
+
return Promise.resolve({
|
|
42
|
+
contextUrl: null,
|
|
43
|
+
documentUrl: url,
|
|
44
|
+
document: structuredClone(document)
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
return Object.assign(loader, { fetched });
|
|
48
|
+
}
|
|
49
|
+
async function sign(document, privateKey = ed25519PrivateKey, verificationMethod = didKeyId) {
|
|
50
|
+
const proofConfig = {
|
|
51
|
+
"@context": document["@context"],
|
|
52
|
+
type: "DataIntegrityProof",
|
|
53
|
+
cryptosuite: "eddsa-jcs-2022",
|
|
54
|
+
verificationMethod,
|
|
55
|
+
proofPurpose: "assertionMethod",
|
|
56
|
+
created: "2023-02-24T23:36:38Z"
|
|
57
|
+
};
|
|
58
|
+
const encoder = new TextEncoder();
|
|
59
|
+
const proofDigest = await crypto.subtle.digest("SHA-256", encoder.encode(serialize(proofConfig)));
|
|
60
|
+
const messageDigest = await crypto.subtle.digest("SHA-256", encoder.encode(serialize(document)));
|
|
61
|
+
const digest = /* @__PURE__ */ new Uint8Array(64);
|
|
62
|
+
digest.set(new Uint8Array(proofDigest), 0);
|
|
63
|
+
digest.set(new Uint8Array(messageDigest), 32);
|
|
64
|
+
const signature = await crypto.subtle.sign("Ed25519", privateKey, digest);
|
|
65
|
+
return {
|
|
66
|
+
...document,
|
|
67
|
+
proof: {
|
|
68
|
+
...proofConfig,
|
|
69
|
+
proofValue: new TextDecoder().decode(encodeMultibase("base58btc", new Uint8Array(signature)))
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async function actorJson(options = {}) {
|
|
74
|
+
const id = parseIri(options.id ?? actorId);
|
|
75
|
+
const key = options.key ?? keyId;
|
|
76
|
+
const json = await new Person({
|
|
77
|
+
id,
|
|
78
|
+
preferredUsername: "alice",
|
|
79
|
+
inbox: parseIri(`${options.id ?? actorId}/inbox`),
|
|
80
|
+
gateways: (options.gateways ?? [gw1, gw2]).map((g) => new URL(g)),
|
|
81
|
+
assertionMethods: options.assertionMethod === false ? [] : [new Multikey({
|
|
82
|
+
id: key,
|
|
83
|
+
controller: id,
|
|
84
|
+
publicKey: gatewayPublicKey
|
|
85
|
+
})],
|
|
86
|
+
publicKeys: options.publicKey === null ? [] : [new CryptographicKey({
|
|
87
|
+
id: key,
|
|
88
|
+
owner: id,
|
|
89
|
+
publicKey: options.publicKey ?? gatewayPublicKey
|
|
90
|
+
})]
|
|
91
|
+
}).toJsonLd({
|
|
92
|
+
format: "compact",
|
|
93
|
+
contextLoader
|
|
94
|
+
});
|
|
95
|
+
const context = json["@context"];
|
|
96
|
+
if (!context.includes("https://w3id.org/security/data-integrity/v1")) json["@context"] = [...context, "https://w3id.org/security/data-integrity/v1"];
|
|
97
|
+
return json;
|
|
98
|
+
}
|
|
99
|
+
async function signedRequest(spec, key = keyId) {
|
|
100
|
+
return await signRequest(new Request("https://recipient.example/inbox", {
|
|
101
|
+
method: "POST",
|
|
102
|
+
body: "{}",
|
|
103
|
+
headers: { "Content-Type": "application/activity+json" }
|
|
104
|
+
}), rsaPrivateKey2, key, { spec });
|
|
105
|
+
}
|
|
106
|
+
test("verifyRequest() accepts gateway keys vouched for by portable actors", async () => {
|
|
107
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await actorJson()) });
|
|
108
|
+
for (const spec of ["draft-cavage-http-signatures-12", "rfc9421"]) {
|
|
109
|
+
const key = await verifyRequest(await signedRequest(spec), {
|
|
110
|
+
documentLoader,
|
|
111
|
+
contextLoader,
|
|
112
|
+
spec
|
|
113
|
+
});
|
|
114
|
+
ok(key != null, spec);
|
|
115
|
+
strictEqual(key.id?.href, keyId.href);
|
|
116
|
+
strictEqual(key.ownerId?.href, parseIri(actorId).href);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
test("verifyRequest() accepts gateway keys only in assertionMethod", async () => {
|
|
120
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await actorJson({ publicKey: null })) });
|
|
121
|
+
strictEqual((await verifyRequest(await signedRequest(), {
|
|
122
|
+
documentLoader,
|
|
123
|
+
contextLoader
|
|
124
|
+
}))?.id?.href, keyId.href);
|
|
125
|
+
});
|
|
126
|
+
test("verifyRequest() rejects gateway keys that portable actors do not vouch for", async () => {
|
|
127
|
+
const unsigned = await actorJson();
|
|
128
|
+
const cases = {
|
|
129
|
+
"an unsigned actor document": unsigned,
|
|
130
|
+
"an actor document signed by another DID": await sign(unsigned, otherKeyPair.privateKey, `${otherDid}#${otherDid.slice(8)}`),
|
|
131
|
+
"an unlisted gateway": await sign(await actorJson({ gateways: [gw2] })),
|
|
132
|
+
"a key missing from assertionMethod": await sign(await actorJson({ assertionMethod: false })),
|
|
133
|
+
"a key referred to by URL": await sign({
|
|
134
|
+
...await actorJson({
|
|
135
|
+
publicKey: null,
|
|
136
|
+
assertionMethod: false
|
|
137
|
+
}),
|
|
138
|
+
assertionMethod: [keyId.href]
|
|
139
|
+
}),
|
|
140
|
+
"a publicKey entry with other key material": await sign(await actorJson({ publicKey: rsaPublicKey3.publicKey })),
|
|
141
|
+
"a key ID for another actor": await sign(await actorJson({ key: new URL(`${compatibleId(gw1, `${actorId}/other`)}#main-key`) }))
|
|
142
|
+
};
|
|
143
|
+
for (const [name, document] of Object.entries(cases)) {
|
|
144
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: document });
|
|
145
|
+
strictEqual(await verifyRequest(await signedRequest(), {
|
|
146
|
+
documentLoader,
|
|
147
|
+
contextLoader
|
|
148
|
+
}), null, name);
|
|
149
|
+
}
|
|
150
|
+
const otherActorKey = new URL(`${compatibleId(gw1, `${actorId}/other`)}#main-key`);
|
|
151
|
+
const documentLoader = createLoader({ [compatibleId(gw1, `${actorId}/other`)]: await sign(await actorJson()) });
|
|
152
|
+
strictEqual(await verifyRequest(await signedRequest(void 0, otherActorKey), {
|
|
153
|
+
documentLoader,
|
|
154
|
+
contextLoader
|
|
155
|
+
}), null);
|
|
156
|
+
});
|
|
157
|
+
test("verifyRequest() keeps web-origin trust for compatible-ID actors", async () => {
|
|
158
|
+
const id = compatibleId(gw1);
|
|
159
|
+
const documentLoader = createLoader({ [id]: await actorJson({
|
|
160
|
+
id,
|
|
161
|
+
gateways: [gw1]
|
|
162
|
+
}) });
|
|
163
|
+
const key = await verifyRequest(await signedRequest(), {
|
|
164
|
+
documentLoader,
|
|
165
|
+
contextLoader
|
|
166
|
+
});
|
|
167
|
+
strictEqual(key?.id?.href, keyId.href);
|
|
168
|
+
strictEqual(key?.ownerId?.href, id);
|
|
169
|
+
});
|
|
170
|
+
test("gateway keys are neither cached nor accepted outside HTTP Signatures", async () => {
|
|
171
|
+
const calls = [];
|
|
172
|
+
const keyCache = {
|
|
173
|
+
get(id) {
|
|
174
|
+
calls.push(`get ${id.href}`);
|
|
175
|
+
return Promise.resolve(void 0);
|
|
176
|
+
},
|
|
177
|
+
set(id) {
|
|
178
|
+
calls.push(`set ${id.href}`);
|
|
179
|
+
return Promise.resolve();
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: await sign(await actorJson()) });
|
|
183
|
+
ok(await verifyRequest(await signedRequest(), {
|
|
184
|
+
documentLoader,
|
|
185
|
+
contextLoader,
|
|
186
|
+
keyCache
|
|
187
|
+
}) != null);
|
|
188
|
+
const fetchOptions = {
|
|
189
|
+
documentLoader,
|
|
190
|
+
contextLoader,
|
|
191
|
+
keyCache
|
|
192
|
+
};
|
|
193
|
+
strictEqual((await fetchKey(keyId, CryptographicKey, fetchOptions)).key, null);
|
|
194
|
+
strictEqual((await fetchKey(keyId, Multikey, fetchOptions)).key, null);
|
|
195
|
+
deepStrictEqual(calls.filter((c) => c.includes(keyId.origin)), []);
|
|
196
|
+
});
|
|
197
|
+
test("doesActorOwnKey() and getKeyOwner() resolve gateway keys to portable actors", async () => {
|
|
198
|
+
const options = {
|
|
199
|
+
documentLoader: createLoader({ [compatibleId(gw1)]: await sign(await actorJson()) }),
|
|
200
|
+
contextLoader
|
|
201
|
+
};
|
|
202
|
+
const key = await verifyRequest(await signedRequest(), options);
|
|
203
|
+
ok(key != null);
|
|
204
|
+
const activity = (actor) => new Create({
|
|
205
|
+
id: parseIri(`ap+ef61://${did}/activities/1`),
|
|
206
|
+
actor: parseIri(actor)
|
|
207
|
+
});
|
|
208
|
+
ok(await doesActorOwnKey(activity(actorId), key, options));
|
|
209
|
+
ok(await doesActorOwnKey(activity(compatibleId(gw2)), key, options));
|
|
210
|
+
ok(!await doesActorOwnKey(activity(`${actorId}/other`), key, options));
|
|
211
|
+
strictEqual((await getKeyOwner(keyId, options))?.id?.href, parseIri(actorId).href);
|
|
212
|
+
strictEqual((await getKeyOwner(key, options))?.id?.href, key.ownerId?.href);
|
|
213
|
+
const forged = key.clone({ publicKey: rsaPublicKey3.publicKey });
|
|
214
|
+
strictEqual(await getKeyOwner(forged, options), null);
|
|
215
|
+
ok(!await doesActorOwnKey(activity(actorId), forged, options));
|
|
216
|
+
});
|
|
217
|
+
test("doesActorOwnKey() and getKeyOwner() do not fall back for rejected gateway keys", async () => {
|
|
218
|
+
const options = {
|
|
219
|
+
documentLoader: createLoader({ [compatibleId(gw1)]: await actorJson() }),
|
|
220
|
+
contextLoader
|
|
221
|
+
};
|
|
222
|
+
const key = new CryptographicKey({
|
|
223
|
+
id: keyId,
|
|
224
|
+
owner: parseIri(actorId),
|
|
225
|
+
publicKey: gatewayPublicKey
|
|
226
|
+
});
|
|
227
|
+
ok(!await doesActorOwnKey(new Create({
|
|
228
|
+
id: parseIri(`ap+ef61://${did}/activities/1`),
|
|
229
|
+
actor: parseIri(actorId)
|
|
230
|
+
}), key, options));
|
|
231
|
+
strictEqual(await getKeyOwner(keyId, options), null);
|
|
232
|
+
strictEqual(await getKeyOwner(key, options), null);
|
|
233
|
+
});
|
|
234
|
+
test("verifyRequest() binds gateway keys to the actor whose document is signed", async () => {
|
|
235
|
+
const attackerDid = otherDid;
|
|
236
|
+
const attackerActorId = `ap+ef61://${attackerDid}/actor`;
|
|
237
|
+
const shiftingContext = "https://attacker.example/context";
|
|
238
|
+
let loads = 0;
|
|
239
|
+
const shiftingContextLoader = (url) => {
|
|
240
|
+
if (url !== shiftingContext) return contextLoader(url);
|
|
241
|
+
loads++;
|
|
242
|
+
const document = { "@context": loads <= 2 ? {
|
|
243
|
+
victimId: "@id",
|
|
244
|
+
attackerId: "https://attacker.example/ns#a"
|
|
245
|
+
} : {
|
|
246
|
+
victimId: "https://attacker.example/ns#v",
|
|
247
|
+
attackerId: "@id"
|
|
248
|
+
} };
|
|
249
|
+
return Promise.resolve({
|
|
250
|
+
contextUrl: null,
|
|
251
|
+
documentUrl: url,
|
|
252
|
+
document
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
const { id: _, ...victim } = await actorJson({ gateways: [gw1] });
|
|
256
|
+
const document = await sign({
|
|
257
|
+
...victim,
|
|
258
|
+
"@context": [...victim["@context"], shiftingContext],
|
|
259
|
+
victimId: actorId,
|
|
260
|
+
attackerId: attackerActorId
|
|
261
|
+
}, otherKeyPair.privateKey, `${attackerDid}#${attackerDid.slice(8)}`);
|
|
262
|
+
const documentLoader = createLoader({ [compatibleId(gw1)]: document });
|
|
263
|
+
strictEqual(await verifyRequest(await signedRequest(), {
|
|
264
|
+
documentLoader,
|
|
265
|
+
contextLoader: shiftingContextLoader
|
|
266
|
+
}), null);
|
|
267
|
+
ok(loads > 2, "the shifting context was loaded for the proof");
|
|
268
|
+
loads = 0;
|
|
269
|
+
strictEqual(await getKeyOwner(keyId, {
|
|
270
|
+
documentLoader,
|
|
271
|
+
contextLoader: shiftingContextLoader
|
|
272
|
+
}), null);
|
|
273
|
+
});
|
|
274
|
+
//#endregion
|
|
275
|
+
export {};
|
package/dist/sig/proof.test.mjs
CHANGED
|
@@ -9,11 +9,11 @@ import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
|
|
|
9
9
|
import "../std__assert-DvMDRPes.mjs";
|
|
10
10
|
import { t as assertRejects } from "../assert_rejects-CTptdYck.mjs";
|
|
11
11
|
import { t as assert } from "../assert-D1Eafmd_.mjs";
|
|
12
|
-
import { l as verifyRequest } from "../http-f1qaBtOh.mjs";
|
|
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-_aSNLA90.mjs";
|
|
15
12
|
import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-4IJqPYos.mjs";
|
|
16
|
-
import { a as verifyObject, l as verifyProof, n as hasProofLike, o as verifyPortableObjectProof, r as signObject, t as createProof } from "../proof-
|
|
13
|
+
import { a as verifyObject, l as verifyProof, n as hasProofLike, o as verifyPortableObjectProof, r as signObject, t as createProof } from "../proof-B6gwdhN5.mjs";
|
|
14
|
+
import { l as verifyRequest } from "../http-DKWi8RjI.mjs";
|
|
15
|
+
import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
|
|
16
|
+
import { t as getAuthenticatedDocumentLoader } from "../docloader-C6yOVoaF.mjs";
|
|
17
17
|
import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
|
|
18
18
|
import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
19
19
|
import { decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { f as verifyPortableObjectProof, ht as version, m as verifyPortableObjectProofWithRoot, mt as name } from "./http-BoWBwC0g.js";
|
|
4
|
+
import "./owner-1TFakcTF.js";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { CollectionPage, Object as Object$1, isActor } from "@fedify/vocab";
|
|
7
7
|
import { trace } from "@opentelemetry/api";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
3
|
-
|
|
2
|
+
const require_http = require("./http-CuLWIJdf.cjs");
|
|
3
|
+
require("./owner-BXufwAzm.cjs");
|
|
4
4
|
let _logtape_logtape = require("@logtape/logtape");
|
|
5
5
|
let _fedify_vocab = require("@fedify/vocab");
|
|
6
6
|
let _opentelemetry_api = require("@opentelemetry/api");
|
|
@@ -236,7 +236,7 @@ async function fetchOwner(candidate, options) {
|
|
|
236
236
|
contextLoader,
|
|
237
237
|
tracerProvider,
|
|
238
238
|
gateways,
|
|
239
|
-
verifyPortableObject: (document, verifierOptions) =>
|
|
239
|
+
verifyPortableObject: (document, verifierOptions) => require_http.verifyPortableObjectProof(document, {
|
|
240
240
|
...options,
|
|
241
241
|
...verifierOptions
|
|
242
242
|
}),
|
|
@@ -340,7 +340,7 @@ function getSourceGateway(node, documentUrl) {
|
|
|
340
340
|
* @since 2.4.0
|
|
341
341
|
*/
|
|
342
342
|
async function verifyPortableObject(jsonLd, options = {}) {
|
|
343
|
-
const { result, root, objectType } = await
|
|
343
|
+
const { result, root, objectType } = await require_http.verifyPortableObjectProofWithRoot(jsonLd, options);
|
|
344
344
|
if (result.verified) {
|
|
345
345
|
const node = objectType === "collection" && root != null ? describeRoot(root) : null;
|
|
346
346
|
const chain = node == null ? null : resolveChain(node, options.referrer);
|
|
@@ -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-jyjdrWjG.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-CPx4ZWwt.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
|
@@ -348,6 +348,25 @@ type ActorKeyPairsDispatcher<TContextData> = (context: Context<TContextData>, id
|
|
|
348
348
|
* @since 0.15.0
|
|
349
349
|
*/
|
|
350
350
|
type ActorHandleMapper<TContextData> = (context: Context<TContextData>, username: string) => string | null | Promise<string | null>;
|
|
351
|
+
/**
|
|
352
|
+
* A callback that maps an actor's internal identifier to the ID of the
|
|
353
|
+
* [FEP-ef61] portable actor it dispatches, or `null` if the actor is not
|
|
354
|
+
* portable.
|
|
355
|
+
*
|
|
356
|
+
* The returned ID is an `ap:` or `ap+ef61:` URI, e.g.,
|
|
357
|
+
* `ap+ef61://did:key:z6Mk.../actors/alice`, or its compatible identifier.
|
|
358
|
+
* It must be the same ID that the actor dispatcher puts in the actor's `id`,
|
|
359
|
+
* and must not have a fragment.
|
|
360
|
+
*
|
|
361
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
362
|
+
*
|
|
363
|
+
* @template TContextData The context data to pass to the {@link Context}.
|
|
364
|
+
* @param context The context.
|
|
365
|
+
* @param identifier The actor's internal identifier.
|
|
366
|
+
* @returns The portable actor's ID, or `null` if the actor is not portable.
|
|
367
|
+
* @since 2.4.0
|
|
368
|
+
*/
|
|
369
|
+
type PortableActorIdMapper<TContextData> = (context: Context<TContextData>, identifier: string) => URL | null | Promise<URL | null>;
|
|
351
370
|
/**
|
|
352
371
|
* A callback that maps a WebFinger query to the corresponding actor's
|
|
353
372
|
* internal identifier or username, or `null` if the query is not found.
|
|
@@ -2365,6 +2384,30 @@ interface ActorCallbackSetters<TContextData> {
|
|
|
2365
2384
|
* @since 1.4.0
|
|
2366
2385
|
*/
|
|
2367
2386
|
mapAlias(mapper: ActorAliasMapper<TContextData>): ActorCallbackSetters<TContextData>;
|
|
2387
|
+
/**
|
|
2388
|
+
* Sets the callback function that maps an actor's identifier to the ID of
|
|
2389
|
+
* the [FEP-ef61] portable actor it dispatches. If the callback returns
|
|
2390
|
+
* a portable ID for an identifier, the key pairs of that actor are treated
|
|
2391
|
+
* as this server's *gateway keys* for the portable actor:
|
|
2392
|
+
* {@link Context.getActorKeyPairs} derives their key IDs from the actor's
|
|
2393
|
+
* compatible identifier on this server, e.g.,
|
|
2394
|
+
* `https://example.com/.well-known/apgateway/did:key:z6Mk.../actors/alice#main-key`,
|
|
2395
|
+
* and makes the portable actor their owner, so that requests this server
|
|
2396
|
+
* makes on behalf of the actor, such as activity deliveries and signed
|
|
2397
|
+
* fetches, are signed with them. Gateway keys are only used for HTTP
|
|
2398
|
+
* Signatures; they never make Object Integrity Proofs or Linked Data
|
|
2399
|
+
* Signatures.
|
|
2400
|
+
*
|
|
2401
|
+
* If it's omitted, or it returns `null`, the actor's keys are derived from
|
|
2402
|
+
* {@link Context.getActorUri} as usual.
|
|
2403
|
+
*
|
|
2404
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
2405
|
+
* @param mapper A callback that maps an actor's identifier to its portable
|
|
2406
|
+
* ID, or `null` if the actor is not portable.
|
|
2407
|
+
* @returns The setters object so that settings can be chained.
|
|
2408
|
+
* @since 2.4.0
|
|
2409
|
+
*/
|
|
2410
|
+
mapPortableActorId(mapper: PortableActorIdMapper<TContextData>): ActorCallbackSetters<TContextData>;
|
|
2368
2411
|
/**
|
|
2369
2412
|
* Maps a fixed path to a sentinel identifier. It is useful for exposing
|
|
2370
2413
|
* a single, instance-level actor at a fixed path, such as `/actor` for
|
|
@@ -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-DKWi8RjI.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-C6yOVoaF.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-d8EjO29d.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-DE8kSNQU.cjs");
|
|
4
4
|
exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
|
|
5
5
|
exports.kvCache = require_kv_cache.kvCache;
|
package/dist/utils/mod.d.cts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
|
-
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-
|
|
2
|
+
import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../mod-xGFCHqq_.cjs";
|
|
3
3
|
export { getAuthenticatedDocumentLoader, kvCache };
|
package/dist/utils/mod.d.ts
CHANGED
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-BdnmnAVc.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.2071+8b9dccb9",
|
|
4
4
|
"description": "An ActivityPub server framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ActivityPub",
|
|
@@ -151,10 +151,10 @@
|
|
|
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.2071+8b9dccb9",
|
|
155
|
+
"@fedify/vocab": "2.4.0-dev.2071+8b9dccb9",
|
|
156
|
+
"@fedify/vocab-runtime": "2.4.0-dev.2071+8b9dccb9",
|
|
157
|
+
"@fedify/webfinger": "2.4.0-dev.2071+8b9dccb9"
|
|
158
158
|
},
|
|
159
159
|
"devDependencies": {
|
|
160
160
|
"@std/assert": "npm:@jsr/std__assert@^0.226.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.2071+8b9dccb9"
|
|
171
171
|
},
|
|
172
172
|
"scripts": {
|
|
173
173
|
"build:self": "tsdown",
|