@fedify/fedify 2.5.0-dev.2446 → 2.5.0-dev.2492
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/README.md +3 -0
- package/dist/{activity-listener-C-BSbKI7.mjs → activity-listener-CELFAodc.mjs} +8 -4
- package/dist/{builder-Da8b9O6v.mjs → builder-DphK9v7f.mjs} +5 -5
- package/dist/{client-D-XP_Ccb.d.ts → client-3InDZbba.d.cts} +0 -1
- package/dist/{client-D-XP_Ccb.d.cts → client-3InDZbba.d.ts} +0 -1
- package/dist/{client-CEnNz8O7.mjs → client-5SIFzW3q.mjs} +113 -64
- 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-D1djO5fa.mjs → compound-proof-cYtvlTgF.mjs} +2 -2
- package/dist/{context-8Tu9kea0.mjs → context-COHd1Rsh.mjs} +2 -0
- package/dist/{context-BdB54V-A.d.ts → context-DQJE9YfH.d.ts} +332 -6
- package/dist/{context-CQ9H8vNW.d.cts → context-DSuL3YWx.d.cts} +332 -6
- package/dist/{deno-eNpfj4oR.mjs → deno-iOAA7iRN.mjs} +1 -1
- package/dist/docloader-DCZkiTeF.mjs +136 -0
- package/dist/{exporter-DThFfe7P.mjs → exporter-DVG68ozH.mjs} +36 -30
- package/dist/federation/builder.test.mjs +1 -1
- package/dist/federation/compound-fanout.test.mjs +6 -3
- package/dist/federation/handler-compound-proof.test.mjs +5 -5
- package/dist/federation/handler.test.mjs +22 -7
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox-actorless.test.d.mts +2 -0
- package/dist/federation/inbox-actorless.test.mjs +487 -0
- package/dist/federation/inbox-authentication.test.d.mts +2 -0
- package/dist/federation/inbox-authentication.test.mjs +116 -0
- package/dist/federation/inbox-report.test.mjs +5 -5
- package/dist/federation/inbox-view.test.d.mts +2 -0
- package/dist/federation/inbox-view.test.mjs +369 -0
- package/dist/federation/inbox.test.mjs +22 -12
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +470 -35
- package/dist/federation/mod.cjs +2 -1
- package/dist/federation/mod.d.cts +4 -4
- package/dist/federation/mod.d.ts +4 -4
- package/dist/federation/mod.js +8 -2
- package/dist/federation/mq.test.mjs +36 -1
- package/dist/federation/outgoing-proof.test.mjs +9 -6
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-collection.test.mjs +4 -4
- package/dist/federation/portable-delivery.test.mjs +2 -2
- package/dist/federation/portable-gateway-keys.test.mjs +13 -7
- package/dist/federation/portable-inbox.test.mjs +4 -4
- package/dist/federation/portable-parse-uri.test.mjs +1 -1
- package/dist/federation/portable-route-activity.test.mjs +2 -2
- package/dist/federation/portable.test.mjs +3 -3
- package/dist/federation/send.test.mjs +502 -93
- package/dist/federation/tasks/enqueue.test.mjs +3 -3
- package/dist/federation/tasks/tasks.test.mjs +4 -4
- package/dist/federation/temporal.test.mjs +1 -1
- package/dist/federation/webfinger.test.mjs +2 -2
- package/dist/{federation-BVH7drJA.cjs → federation-D0AZw_aw.cjs} +1415 -236
- package/dist/{http-BUJ5SFh6.mjs → http-BoJCMnjY.mjs} +204 -106
- package/dist/{http-DlNxxW_5.js → http-ChXUU_3c.js} +319 -123
- package/dist/{http-BfW3wyQ4.cjs → http-kv1LZw-r.cjs} +339 -125
- package/dist/inbox-BjihTKLo.mjs +312 -0
- package/dist/inbox-authentication-DflPYlLL.mjs +171 -0
- package/dist/inbox-view-D-skypg-.mjs +385 -0
- package/dist/{key-nYGY4QB9.d.cts → key-DbLNT-vA.d.ts} +1 -2
- package/dist/{key-DhsBxxZN.d.ts → key-DlHT4R6k.d.cts} +1 -2
- package/dist/{kv-cache-D_m3A241.mjs → kv-cache-Cmsyke4d.mjs} +1 -1
- package/dist/{kv-cache-7015lbrx.js → kv-cache-DQcte7ES.js} +73 -28
- package/dist/{kv-cache-kkBB0vbI.cjs → kv-cache-Ddh5sMxH.cjs} +72 -27
- package/dist/ld-CWVpo_NM.d.cts +250 -0
- package/dist/{ld-CD2CsPxq.mjs → ld-CdvcOEXQ.mjs} +52 -9
- package/dist/ld-Inagww4R.d.ts +250 -0
- package/dist/{metrics-D3LHk6Z4.mjs → metrics-CpxvUrBz.mjs} +1 -1
- package/dist/{middleware-N9eM16XE.js → middleware-BHb5toqA.js} +1413 -247
- package/dist/{middleware-CCDXvXOG.mjs → middleware-BKs2DLUF.mjs} +1 -1
- package/dist/{middleware-CzoWvrdZ.mjs → middleware-CoBLrTKX.mjs} +533 -132
- package/dist/{mod-B0dGgQsg.d.cts → mod-6TQ4UQZb.d.cts} +1 -1
- package/dist/mod-B4kBw1-8.d.ts +154 -0
- package/dist/{mod-DkhfZC1u.d.ts → mod-B7j30IQf.d.ts} +2 -9
- package/dist/mod-C1nT74IG.d.cts +154 -0
- package/dist/{mod-D0bxB8jS.d.ts → mod-CIeBgsOC.d.ts} +1 -1
- package/dist/{mod-B5-wdzmJ.d.cts → mod-YvA4Rk8J.d.cts} +2 -9
- package/dist/mod.cjs +6 -5
- package/dist/mod.d.cts +9 -9
- package/dist/mod.d.ts +9 -9
- package/dist/mod.js +6 -6
- package/dist/{mq-Dm1Wmtm-.mjs → mq-eF96QxUT.mjs} +6 -0
- package/dist/nodeinfo/client.test.mjs +337 -19
- package/dist/nodeinfo/handler.test.mjs +2 -2
- package/dist/nodeinfo/mod.cjs +1 -1
- package/dist/nodeinfo/mod.d.cts +1 -1
- package/dist/nodeinfo/mod.d.ts +1 -1
- package/dist/nodeinfo/mod.js +1 -1
- package/dist/otel/exporter.test.mjs +257 -1
- package/dist/otel/mod.cjs +36 -30
- package/dist/otel/mod.d.cts +13 -0
- package/dist/otel/mod.d.ts +13 -0
- package/dist/otel/mod.js +36 -30
- package/dist/{owner-C5-FVX6t.mjs → owner-DTnVpUKA.mjs} +3 -3
- package/dist/{portable-collection-Cony3_LC.mjs → portable-collection-CJeYTL61.mjs} +2 -2
- package/dist/{portable-collection-C-Z1SKDy.cjs → portable-collection-DciwBIia.cjs} +1 -1
- package/dist/{portable-collection-CC2zNAje.js → portable-collection-TmtpzD4E.js} +1 -1
- package/dist/{portable-key-DNc_flH-.mjs → portable-key-DcYok4ki.mjs} +1 -1
- package/dist/{proof-Cryb1c70.mjs → proof-GH7Poos_.mjs} +98 -10
- package/dist/{send-AF25pWaJ.mjs → send-BgGJh6pv.mjs} +174 -76
- 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 +553 -2
- package/dist/sig/key.test.mjs +1 -1
- package/dist/sig/ld.test.mjs +1 -1
- package/dist/sig/mitra-receive-interop.test.mjs +4 -4
- package/dist/sig/mitra-send-interop.test.mjs +3 -3
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.d.cts +3 -3
- package/dist/sig/mod.d.ts +3 -3
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +1 -1
- package/dist/sig/portable-collection.test.mjs +1 -1
- package/dist/sig/portable-interop.test.mjs +3 -3
- package/dist/sig/portable-key.test.mjs +5 -5
- package/dist/sig/proof.test.mjs +45 -5
- package/dist/sig/tootik-request-interop.test.mjs +4 -4
- package/dist/sig/tootik-send-interop.test.mjs +3 -3
- package/dist/sig/verification.test.mjs +3 -3
- package/dist/{temporal-BsAeuUJj.mjs → temporal-gJINzcL4.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +288 -2
- package/dist/testing/mod.mjs +2 -2
- package/dist/{testing-t8xDeJZ5.mjs → testing-Dbr21vZk.mjs} +1 -1
- package/dist/{types-_S2_MeLF.js → types-DUjZb4i6.js} +112 -63
- package/dist/{types-poIao40f.cjs → types-hKCCjii0.cjs} +111 -62
- package/dist/utils/docloader.test.mjs +344 -36
- 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 +7 -7
- package/dist/docloader-B-0nqOB1.mjs +0 -91
- package/dist/inbox-CHvMaIFX.mjs +0 -188
- package/dist/mod-BRpER-B0.d.ts +0 -320
- package/dist/mod-xAfaLS4T.d.cts +0 -320
- package/dist/owner-BF0L9cMt.d.cts +0 -78
- package/dist/owner-BSzr5-I8.d.ts +0 -78
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-kv1LZw-r.cjs");
|
|
3
3
|
let _logtape_logtape = require("@logtape/logtape");
|
|
4
4
|
let _fedify_vocab_runtime = require("@fedify/vocab-runtime");
|
|
5
5
|
let es_toolkit = require("es-toolkit");
|
|
6
|
+
let _fedify_vocab_runtime_internal = require("@fedify/vocab-runtime/internal");
|
|
6
7
|
//#region src/utils/docloader.ts
|
|
7
8
|
const logger$1 = (0, _logtape_logtape.getLogger)([
|
|
8
9
|
"fedify",
|
|
@@ -26,13 +27,35 @@ const DEFAULT_MAX_REDIRECTION = 20;
|
|
|
26
27
|
* @throws {RangeError} If the `timeout` option is invalid.
|
|
27
28
|
* @since 0.4.0
|
|
28
29
|
*/
|
|
29
|
-
function getAuthenticatedDocumentLoader(identity,
|
|
30
|
+
function getAuthenticatedDocumentLoader(identity, options = {}) {
|
|
31
|
+
return createAuthenticatedDocumentLoader(identity, options);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The placeholder that the alternate document callback of
|
|
35
|
+
* `getRemoteDocument()` returns, so that the alternate document is loaded
|
|
36
|
+
* after the current hop is closed.
|
|
37
|
+
*/
|
|
38
|
+
const ALTERNATE_PLACEHOLDER = Object.freeze({
|
|
39
|
+
contextUrl: null,
|
|
40
|
+
document: null,
|
|
41
|
+
documentUrl: "about:blank"
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* The implementation of {@link getAuthenticatedDocumentLoader}. This is not
|
|
45
|
+
* exported from any entry point.
|
|
46
|
+
* @param identity The identity to get the document loader for.
|
|
47
|
+
* @param options The options for the document loader.
|
|
48
|
+
* @param deps The dependencies, for tests.
|
|
49
|
+
* @returns The authenticated document loader.
|
|
50
|
+
* @throws {TypeError} If the key is invalid or unsupported.
|
|
51
|
+
*/
|
|
52
|
+
function createAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedirection, userAgent, specDeterminer, timeout, tracerProvider } = {}, deps = {}) {
|
|
30
53
|
require_http.validateCryptoKey(identity.privateKey);
|
|
31
54
|
const resolvedTimeout = (0, _fedify_vocab_runtime.resolveDocumentLoaderTimeout)(timeout);
|
|
32
55
|
async function load(url, options, redirected = 0, visited = /* @__PURE__ */ new Set()) {
|
|
33
56
|
options?.signal?.throwIfAborted();
|
|
34
57
|
let currentUrl = new URL(url).href;
|
|
35
|
-
|
|
58
|
+
validateUrl(currentUrl);
|
|
36
59
|
visited.add(currentUrl);
|
|
37
60
|
const originalRequest = (0, _fedify_vocab_runtime.createActivityPubRequest)(currentUrl, { userAgent });
|
|
38
61
|
function follow(nextUrl) {
|
|
@@ -41,46 +64,68 @@ function getAuthenticatedDocumentLoader(identity, { allowPrivateAddress, maxRedi
|
|
|
41
64
|
if (visited.has(nextUrl)) throw new _fedify_vocab_runtime.FetchError(currentUrl, `Redirect loop detected: ${nextUrl}`);
|
|
42
65
|
redirected++;
|
|
43
66
|
}
|
|
44
|
-
const
|
|
67
|
+
const result = await require_http.doubleKnockScoped(originalRequest, identity, {
|
|
45
68
|
maxRedirection,
|
|
46
69
|
specDeterminer,
|
|
47
70
|
log: (0, es_toolkit.curry)(_fedify_vocab_runtime.logRequest)(logger$1),
|
|
48
71
|
tracerProvider,
|
|
49
72
|
signal: options?.signal,
|
|
50
|
-
validateRedirect:
|
|
73
|
+
validateRedirect: (nextUrl) => {
|
|
51
74
|
follow(nextUrl);
|
|
52
|
-
|
|
75
|
+
validateUrl(nextUrl);
|
|
53
76
|
visited.add(nextUrl);
|
|
54
77
|
currentUrl = nextUrl;
|
|
55
78
|
}
|
|
79
|
+
}, (hopUrl) => openHop(hopUrl, options), async (response) => {
|
|
80
|
+
options?.signal?.throwIfAborted();
|
|
81
|
+
let alternateUrl;
|
|
82
|
+
const document = await (0, _fedify_vocab_runtime.getRemoteDocument)(currentUrl, response, (url) => {
|
|
83
|
+
alternateUrl = url;
|
|
84
|
+
return Promise.resolve(ALTERNATE_PLACEHOLDER);
|
|
85
|
+
}, options);
|
|
86
|
+
if (alternateUrl == null) return { document };
|
|
87
|
+
if (!response.bodyUsed && response.body?.locked !== true) response.body?.cancel().catch((error) => {
|
|
88
|
+
logger$1.debug("Failed to cancel the response body from {url}: {error}", {
|
|
89
|
+
url: currentUrl,
|
|
90
|
+
error
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
return { alternateUrl };
|
|
56
94
|
});
|
|
57
95
|
options?.signal?.throwIfAborted();
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
96
|
+
if ("document" in result) return result.document;
|
|
97
|
+
follow(result.alternateUrl);
|
|
98
|
+
return load(result.alternateUrl, options, redirected, visited);
|
|
99
|
+
}
|
|
100
|
+
function openUnvalidatedHop(url, signal) {
|
|
101
|
+
if (deps.openHop != null) return deps.openHop(url);
|
|
102
|
+
return allowPrivateAddress ? (0, _fedify_vocab_runtime_internal.openDirectFetch)(url) : (0, _fedify_vocab_runtime_internal.openPublicFetch)(url, { signal });
|
|
62
103
|
}
|
|
63
|
-
async function
|
|
104
|
+
async function openHop(url, options) {
|
|
105
|
+
try {
|
|
106
|
+
const session = await openUnvalidatedHop(url, options?.signal);
|
|
107
|
+
if (options?.signal?.aborted) {
|
|
108
|
+
await session.close();
|
|
109
|
+
options.signal.throwIfAborted();
|
|
110
|
+
}
|
|
111
|
+
return session;
|
|
112
|
+
} catch (error) {
|
|
113
|
+
if (error instanceof _fedify_vocab_runtime.UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
114
|
+
url,
|
|
115
|
+
error
|
|
116
|
+
});
|
|
117
|
+
else logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
118
|
+
url,
|
|
119
|
+
error
|
|
120
|
+
});
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function validateUrl(url) {
|
|
64
125
|
const parsedUrl = new URL(url);
|
|
65
126
|
const protocol = parsedUrl.protocol;
|
|
66
127
|
if (protocol !== "http:" && protocol !== "https:") throw new _fedify_vocab_runtime.UrlError(`Unsupported protocol: ${protocol}`);
|
|
67
128
|
if (parsedUrl.username !== "" || parsedUrl.password !== "") throw new _fedify_vocab_runtime.UrlError("URLs with credentials are not allowed");
|
|
68
|
-
if (!allowPrivateAddress) {
|
|
69
|
-
try {
|
|
70
|
-
await (0, _fedify_vocab_runtime.validatePublicUrl)(url);
|
|
71
|
-
} catch (error) {
|
|
72
|
-
if (error instanceof _fedify_vocab_runtime.UrlError) if (error.reason === "dns") logger$1.debug("DNS lookup failed for {url}", {
|
|
73
|
-
url,
|
|
74
|
-
error
|
|
75
|
-
});
|
|
76
|
-
else logger$1[options?.suppressError ? "warn" : "error"]("Disallowed private URL: {url}", {
|
|
77
|
-
url,
|
|
78
|
-
error
|
|
79
|
-
});
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
options?.signal?.throwIfAborted();
|
|
83
|
-
}
|
|
84
129
|
}
|
|
85
130
|
return (0, _fedify_vocab_runtime.withDocumentLoaderTimeout)((url, options) => load(url, options), resolvedTimeout);
|
|
86
131
|
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/// <reference lib="esnext.temporal" />
|
|
2
|
+
import { a as KeyCache, v as VerificationObservationOptions } from "./key-DlHT4R6k.cjs";
|
|
3
|
+
import { Activity, Actor, CryptographicKey } from "@fedify/vocab";
|
|
4
|
+
import { DocumentLoader } from "@fedify/vocab-runtime";
|
|
5
|
+
import { MeterProvider, TracerProvider } from "@opentelemetry/api";
|
|
6
|
+
|
|
7
|
+
//#region src/sig/owner.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* Options for {@link doesActorOwnKey}.
|
|
10
|
+
* @since 0.8.0
|
|
11
|
+
*/
|
|
12
|
+
interface DoesActorOwnKeyOptions {
|
|
13
|
+
/**
|
|
14
|
+
* The document loader to use for fetching the actor.
|
|
15
|
+
*/
|
|
16
|
+
documentLoader?: DocumentLoader;
|
|
17
|
+
/**
|
|
18
|
+
* The context loader to use for JSON-LD context retrieval.
|
|
19
|
+
*/
|
|
20
|
+
contextLoader?: DocumentLoader;
|
|
21
|
+
/**
|
|
22
|
+
* The OpenTelemetry tracer provider to use for tracing. If omitted,
|
|
23
|
+
* the global tracer provider is used.
|
|
24
|
+
* @since 1.3.0
|
|
25
|
+
*/
|
|
26
|
+
tracerProvider?: TracerProvider;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Checks if the actor of the given activity owns the specified key.
|
|
30
|
+
*
|
|
31
|
+
* Ownership is never taken from what the activity or the key say about
|
|
32
|
+
* themselves, as both are written by whoever sent the activity. It is
|
|
33
|
+
* established from a document that the owner itself serves: either the key's
|
|
34
|
+
* claimed owner links back to the key, or the actor the activity claims lists
|
|
35
|
+
* the key as its own.
|
|
36
|
+
*
|
|
37
|
+
* @param activity The activity to check.
|
|
38
|
+
* @param key The public key to check.
|
|
39
|
+
* @param options Options for checking the key ownership.
|
|
40
|
+
* @returns Whether the actor is the owner of the key.
|
|
41
|
+
*/
|
|
42
|
+
declare function doesActorOwnKey(activity: Activity, key: CryptographicKey, options: DoesActorOwnKeyOptions): Promise<boolean>;
|
|
43
|
+
/**
|
|
44
|
+
* Options for {@link getKeyOwner}.
|
|
45
|
+
* @since 0.8.0
|
|
46
|
+
*/
|
|
47
|
+
interface GetKeyOwnerOptions {
|
|
48
|
+
/**
|
|
49
|
+
* The document loader to use for fetching the key and its owner.
|
|
50
|
+
*/
|
|
51
|
+
documentLoader?: DocumentLoader;
|
|
52
|
+
/**
|
|
53
|
+
* The context loader to use for JSON-LD context retrieval.
|
|
54
|
+
*/
|
|
55
|
+
contextLoader?: DocumentLoader;
|
|
56
|
+
/**
|
|
57
|
+
* The OpenTelemetry tracer provider to use for tracing. If omitted,
|
|
58
|
+
* the global tracer provider is used.
|
|
59
|
+
* @since 1.3.0
|
|
60
|
+
*/
|
|
61
|
+
tracerProvider?: TracerProvider;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Gets the actor that owns the specified key. Returns `null` if the key has no
|
|
65
|
+
* known owner.
|
|
66
|
+
*
|
|
67
|
+
* The owner is only returned when the key and the owner link to each other:
|
|
68
|
+
* a document that merely claims to own a key is not enough, as the claim and
|
|
69
|
+
* the key can come from the same host.
|
|
70
|
+
*
|
|
71
|
+
* @param keyId The ID of the key to check, or the key itself.
|
|
72
|
+
* @param options Options for getting the key owner.
|
|
73
|
+
* @returns The actor that owns the key, or `null` if the key has no known
|
|
74
|
+
* owner.
|
|
75
|
+
* @since 0.7.0
|
|
76
|
+
*/
|
|
77
|
+
declare function getKeyOwner(keyId: URL | CryptographicKey, options: GetKeyOwnerOptions): Promise<Actor | null>;
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/sig/ld.d.ts
|
|
80
|
+
/**
|
|
81
|
+
* How a context loader marked by {@link markEffectiveContextLoader} already
|
|
82
|
+
* resolves contexts.
|
|
83
|
+
* @internal
|
|
84
|
+
*/
|
|
85
|
+
type EffectiveContextLoaderPolicy = "standard" | "normalization";
|
|
86
|
+
/**
|
|
87
|
+
* A signature of a JSON-LD document.
|
|
88
|
+
* @since 1.0.0
|
|
89
|
+
*/
|
|
90
|
+
interface Signature {
|
|
91
|
+
"@context"?: "https://w3id.org/identity/v1";
|
|
92
|
+
type: "RsaSignature2017";
|
|
93
|
+
id?: string;
|
|
94
|
+
creator: string;
|
|
95
|
+
created: string;
|
|
96
|
+
signatureValue: string;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Attaches a LD signature to the given JSON-LD document.
|
|
100
|
+
* @param jsonLd The JSON-LD document to attach the signature to. It is not
|
|
101
|
+
* modified.
|
|
102
|
+
* @param signature The signature to attach.
|
|
103
|
+
* @returns The JSON-LD document with the attached signature.
|
|
104
|
+
* @throws {TypeError} If the input document is not a valid JSON-LD document.
|
|
105
|
+
* @since 1.0.0
|
|
106
|
+
*/
|
|
107
|
+
declare function attachSignature(jsonLd: unknown, signature: Signature): {
|
|
108
|
+
signature: Signature;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Options for creating Linked Data Signatures.
|
|
112
|
+
* @since 1.0.0
|
|
113
|
+
*/
|
|
114
|
+
interface CreateSignatureOptions {
|
|
115
|
+
/**
|
|
116
|
+
* The context loader for loading remote JSON-LD contexts.
|
|
117
|
+
*/
|
|
118
|
+
contextLoader?: DocumentLoader;
|
|
119
|
+
/**
|
|
120
|
+
* The time when the signature was created. If not specified, the current
|
|
121
|
+
* time will be used.
|
|
122
|
+
*/
|
|
123
|
+
created?: Temporal.Instant;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Creates a LD signature for the given JSON-LD document.
|
|
127
|
+
* @param jsonLd The JSON-LD document to sign.
|
|
128
|
+
* @param privateKey The private key to sign the document.
|
|
129
|
+
* @param keyId The ID of the public key that corresponds to the private key.
|
|
130
|
+
* @param options Additional options for creating the signature.
|
|
131
|
+
* See also {@link CreateSignatureOptions}.
|
|
132
|
+
* @return The created signature.
|
|
133
|
+
* @throws {TypeError} If the private key is invalid or unsupported.
|
|
134
|
+
* @since 1.0.0
|
|
135
|
+
*/
|
|
136
|
+
declare function createSignature(jsonLd: unknown, privateKey: CryptoKey, keyId: URL, {
|
|
137
|
+
contextLoader,
|
|
138
|
+
created
|
|
139
|
+
}?: CreateSignatureOptions): Promise<Signature>;
|
|
140
|
+
/**
|
|
141
|
+
* Options for signing JSON-LD documents.
|
|
142
|
+
* @since 1.0.0
|
|
143
|
+
*/
|
|
144
|
+
interface SignJsonLdOptions extends CreateSignatureOptions {
|
|
145
|
+
/**
|
|
146
|
+
* The OpenTelemetry tracer provider for tracing the signing process.
|
|
147
|
+
* If omitted, the global tracer provider is used.
|
|
148
|
+
* @since 1.3.0
|
|
149
|
+
*/
|
|
150
|
+
tracerProvider?: TracerProvider;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Signs the given JSON-LD document with the private key and returns the signed
|
|
154
|
+
* JSON-LD document.
|
|
155
|
+
* @param jsonLd The JSON-LD document to sign.
|
|
156
|
+
* @param privateKey The private key to sign the document.
|
|
157
|
+
* @param keyId The key ID to use in the signature. It will be used by the
|
|
158
|
+
* verifier to fetch the corresponding public key.
|
|
159
|
+
* @param options Additional options for signing the document.
|
|
160
|
+
* See also {@link SignJsonLdOptions}.
|
|
161
|
+
* @returns The signed JSON-LD document.
|
|
162
|
+
* @throws {TypeError} If the private key is invalid or unsupported.
|
|
163
|
+
* @since 1.0.0
|
|
164
|
+
*/
|
|
165
|
+
declare function signJsonLd(jsonLd: unknown, privateKey: CryptoKey, keyId: URL, options: SignJsonLdOptions): Promise<{
|
|
166
|
+
signature: Signature;
|
|
167
|
+
}>;
|
|
168
|
+
/**
|
|
169
|
+
* Checks if the given JSON-LD document has a Linked Data Signature-like
|
|
170
|
+
* object, without restricting it to a single suite-specific shape.
|
|
171
|
+
* @param jsonLd The JSON-LD document to check.
|
|
172
|
+
* @returns `true` if the document has a signature-like object; `false`
|
|
173
|
+
* otherwise.
|
|
174
|
+
* @since 2.2.0
|
|
175
|
+
*/
|
|
176
|
+
declare function hasSignatureLike(jsonLd: unknown): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Detaches Linked Data Signatures from the given JSON-LD document.
|
|
179
|
+
* @param jsonLd The JSON-LD document to modify.
|
|
180
|
+
* @returns The modified JSON-LD document. If the input document does not
|
|
181
|
+
* contain a signature, the original document is returned.
|
|
182
|
+
* @since 1.0.0
|
|
183
|
+
*/
|
|
184
|
+
declare function detachSignature(jsonLd: unknown): unknown;
|
|
185
|
+
/**
|
|
186
|
+
* Options for verifying Linked Data Signatures.
|
|
187
|
+
* @since 1.0.0
|
|
188
|
+
*/
|
|
189
|
+
interface VerifySignatureOptions extends VerificationObservationOptions {
|
|
190
|
+
/**
|
|
191
|
+
* The document loader to use for fetching the public key.
|
|
192
|
+
*/
|
|
193
|
+
documentLoader?: DocumentLoader;
|
|
194
|
+
/**
|
|
195
|
+
* The context loader to use for JSON-LD context retrieval.
|
|
196
|
+
*/
|
|
197
|
+
contextLoader?: DocumentLoader;
|
|
198
|
+
/**
|
|
199
|
+
* The key cache to use for caching public keys.
|
|
200
|
+
*/
|
|
201
|
+
keyCache?: KeyCache;
|
|
202
|
+
/**
|
|
203
|
+
* The OpenTelemetry tracer provider for tracing the verification process.
|
|
204
|
+
* If omitted, the global tracer provider is used.
|
|
205
|
+
* @since 1.3.0
|
|
206
|
+
*/
|
|
207
|
+
tracerProvider?: TracerProvider;
|
|
208
|
+
/**
|
|
209
|
+
* The OpenTelemetry meter provider. If omitted, the global meter provider
|
|
210
|
+
* is used.
|
|
211
|
+
* @since 2.3.0
|
|
212
|
+
*/
|
|
213
|
+
meterProvider?: MeterProvider;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Verifies Linked Data Signatures of the given JSON-LD document.
|
|
217
|
+
*
|
|
218
|
+
* This is a low-level utility that only checks the cryptographic signature
|
|
219
|
+
* and (optionally) the cached key. It does not run the JSON-LD parsing,
|
|
220
|
+
* attribution, and owner checks that a complete inbound LD verification
|
|
221
|
+
* needs. For incoming activities, prefer {@link verifyJsonLd}, which is
|
|
222
|
+
* the public verification entry point and the one that emits the
|
|
223
|
+
* `activitypub.signature.verification.duration` metric for the LD path.
|
|
224
|
+
* `verifySignature` itself only emits
|
|
225
|
+
* `activitypub.signature.key_fetch.duration`, since the rest of the work
|
|
226
|
+
* that the verification-duration metric is meant to cover happens in
|
|
227
|
+
* `verifyJsonLd`.
|
|
228
|
+
* @param jsonLd The JSON-LD document to verify.
|
|
229
|
+
* @param options Options for verifying the signature.
|
|
230
|
+
* @returns The public key that signed the document or `null` if the signature
|
|
231
|
+
* is invalid or the key is not found.
|
|
232
|
+
* @since 1.0.0
|
|
233
|
+
*/
|
|
234
|
+
declare function verifySignature(jsonLd: unknown, options?: VerifySignatureOptions): Promise<CryptographicKey | null>;
|
|
235
|
+
/**
|
|
236
|
+
* Options for verifying JSON-LD documents.
|
|
237
|
+
*/
|
|
238
|
+
interface VerifyJsonLdOptions extends VerifySignatureOptions {}
|
|
239
|
+
/**
|
|
240
|
+
* Verify the authenticity of the given JSON-LD document using Linked Data
|
|
241
|
+
* Signatures. If the document is signed, this function verifies the signature
|
|
242
|
+
* and checks if the document is attributed to the owner of the public key.
|
|
243
|
+
* If the document is not signed, this function returns `false`.
|
|
244
|
+
* @param jsonLd The JSON-LD document to verify.
|
|
245
|
+
* @param options Options for verifying the document.
|
|
246
|
+
* @returns `true` if the document is authentic; `false` otherwise.
|
|
247
|
+
*/
|
|
248
|
+
declare function verifyJsonLd(jsonLd: unknown, options?: VerifyJsonLdOptions): Promise<boolean>;
|
|
249
|
+
//#endregion
|
|
250
|
+
export { VerifySignatureOptions as a, detachSignature as c, verifyJsonLd as d, verifySignature as f, getKeyOwner as g, doesActorOwnKey as h, VerifyJsonLdOptions as i, hasSignatureLike as l, GetKeyOwnerOptions as m, EffectiveContextLoaderPolicy as n, attachSignature as o, DoesActorOwnKeyOptions as p, SignJsonLdOptions as r, createSignature as s, CreateSignatureOptions as t, signJsonLd as u };
|
|
@@ -3,8 +3,8 @@ import "urlpattern-polyfill";
|
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
4
|
import { c as isPortableActorDocument, d as isPortableUri, l as isPortableId, m as parseKeyIdString, s as isCompatibleKeyId } from "./portable-key-id-Ca30-hOa.mjs";
|
|
5
5
|
import { a as verificationObservation, i as triedKey, n as observeCheck, t as observeAttempt } from "./verification-Dpfcw8ml.mjs";
|
|
6
|
-
import { n as version, t as name } from "./deno-
|
|
7
|
-
import { _ as recordKeyLookup, n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch, t as classifyFetchError } from "./metrics-
|
|
6
|
+
import { n as version, t as name } from "./deno-iOAA7iRN.mjs";
|
|
7
|
+
import { _ as recordKeyLookup, n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch, t as classifyFetchError } from "./metrics-CpxvUrBz.mjs";
|
|
8
8
|
import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
9
9
|
import { getLogger } from "@logtape/logtape";
|
|
10
10
|
import { Activity, CryptographicKey, Multikey, Object as Object$1, getTypeId, isActor } from "@fedify/vocab";
|
|
@@ -200,6 +200,7 @@ async function fetchActorDocumentInternal(actorId, options, propagateContextFetc
|
|
|
200
200
|
actorId: actorId.href,
|
|
201
201
|
error
|
|
202
202
|
});
|
|
203
|
+
if (propagateContextFetchErrors) throw new KeyContextFetchError(error);
|
|
203
204
|
return null;
|
|
204
205
|
}
|
|
205
206
|
let object;
|
|
@@ -1146,8 +1147,26 @@ function createMemoizedDocumentLoader(documentLoader) {
|
|
|
1146
1147
|
return cloneRemoteDocument(await remoteDocument);
|
|
1147
1148
|
};
|
|
1148
1149
|
}
|
|
1150
|
+
const effectiveContextLoaderPolicies = /* @__PURE__ */ new WeakMap();
|
|
1151
|
+
/**
|
|
1152
|
+
* Marks a context loader as the *effective* loader of a policy, i.e., one
|
|
1153
|
+
* that already applies what {@link wrapContextLoaderForJsonLd} (`"standard"`)
|
|
1154
|
+
* or {@link getNormalizationContextLoader} (`"normalization"`) would add.
|
|
1155
|
+
* Those functions return a marked loader as is instead of wrapping it again,
|
|
1156
|
+
* so that a caller can observe every response a parse actually uses,
|
|
1157
|
+
* including Fedify's own baseline contexts.
|
|
1158
|
+
* @param loader The effective context loader.
|
|
1159
|
+
* @param policy The policy the loader already applies.
|
|
1160
|
+
* @returns The given loader.
|
|
1161
|
+
* @internal
|
|
1162
|
+
*/
|
|
1163
|
+
function markEffectiveContextLoader(loader, policy) {
|
|
1164
|
+
effectiveContextLoaderPolicies.set(loader, policy);
|
|
1165
|
+
return loader;
|
|
1166
|
+
}
|
|
1149
1167
|
/** @internal */
|
|
1150
1168
|
function wrapContextLoaderForJsonLd(contextLoader) {
|
|
1169
|
+
if (contextLoader != null && effectiveContextLoaderPolicies.has(contextLoader)) return contextLoader;
|
|
1151
1170
|
const loader = contextLoader ?? builtInContextLoader;
|
|
1152
1171
|
return async (url, options) => {
|
|
1153
1172
|
try {
|
|
@@ -1161,6 +1180,7 @@ function wrapContextLoaderForJsonLd(contextLoader) {
|
|
|
1161
1180
|
}
|
|
1162
1181
|
/** @internal */
|
|
1163
1182
|
function getNormalizationContextLoader(contextLoader) {
|
|
1183
|
+
if (contextLoader != null && effectiveContextLoaderPolicies.get(contextLoader) === "normalization") return contextLoader;
|
|
1164
1184
|
const loader = wrapContextLoaderForJsonLd(contextLoader);
|
|
1165
1185
|
return createMemoizedDocumentLoader(async (url, options) => {
|
|
1166
1186
|
if (URL.canParse(url)) {
|
|
@@ -1613,10 +1633,21 @@ function getLdSignatureObject(jsonLd) {
|
|
|
1613
1633
|
* @returns `true` if the document is authentic; `false` otherwise.
|
|
1614
1634
|
*/
|
|
1615
1635
|
async function verifyJsonLd(jsonLd, options = {}) {
|
|
1616
|
-
return await verifyJsonLdInternal(jsonLd, options, true);
|
|
1636
|
+
return (await verifyJsonLdInternal(jsonLd, options, true)).verified;
|
|
1617
1637
|
}
|
|
1618
1638
|
/** @internal */
|
|
1619
1639
|
async function verifyCompactJsonLd(jsonLd, options = {}) {
|
|
1640
|
+
return (await verifyJsonLdInternal(jsonLd, options, false)).verified;
|
|
1641
|
+
}
|
|
1642
|
+
/**
|
|
1643
|
+
* Same as {@link verifyCompactJsonLd}, but also returns the key that verified
|
|
1644
|
+
* the signature, whose `owner` {@link fetchKey} has confirmed.
|
|
1645
|
+
* @param jsonLd The compacted JSON-LD document to verify.
|
|
1646
|
+
* @param options Options for verifying the JSON-LD document.
|
|
1647
|
+
* @returns The result.
|
|
1648
|
+
* @internal
|
|
1649
|
+
*/
|
|
1650
|
+
async function verifyCompactJsonLdDetailed(jsonLd, options = {}) {
|
|
1620
1651
|
return await verifyJsonLdInternal(jsonLd, options, false);
|
|
1621
1652
|
}
|
|
1622
1653
|
async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
@@ -1626,7 +1657,7 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
1626
1657
|
}, "linkedData", (observation) => verifyJsonLdInternal(jsonLd, {
|
|
1627
1658
|
...options,
|
|
1628
1659
|
[verificationObservation]: observation
|
|
1629
|
-
}, compact), (value) => value);
|
|
1660
|
+
}, compact), (value) => value.verified);
|
|
1630
1661
|
const observation = options[verificationObservation];
|
|
1631
1662
|
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("ld_signatures.verify", async (span) => {
|
|
1632
1663
|
const start = performance.now();
|
|
@@ -1658,12 +1689,18 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
1658
1689
|
const key = await verifySignature(compacted, verificationOptions);
|
|
1659
1690
|
if (key == null) {
|
|
1660
1691
|
if (observation?.attempt != null && !hasLdSignatureProperty(jsonLd)) observation.attempt.reason = { type: "noSignature" };
|
|
1661
|
-
return
|
|
1692
|
+
return {
|
|
1693
|
+
verified: false,
|
|
1694
|
+
key: null
|
|
1695
|
+
};
|
|
1662
1696
|
}
|
|
1663
1697
|
if (key.ownerId == null) {
|
|
1664
1698
|
if (observation?.attempt != null) observation.attempt.reason = { type: "missingOwner" };
|
|
1665
1699
|
logger.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
|
|
1666
|
-
return
|
|
1700
|
+
return {
|
|
1701
|
+
verified: false,
|
|
1702
|
+
key: null
|
|
1703
|
+
};
|
|
1667
1704
|
}
|
|
1668
1705
|
attributions.delete(key.ownerId.href);
|
|
1669
1706
|
if (attributions.size > 0) {
|
|
@@ -1672,10 +1709,16 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
1672
1709
|
attributionIds: [...attributions].map((id) => new URL(id))
|
|
1673
1710
|
};
|
|
1674
1711
|
logger.debug("Some attributions are not authenticated by the Linked Data Signatures: {attributions}.", { attributions: [...attributions] });
|
|
1675
|
-
return
|
|
1712
|
+
return {
|
|
1713
|
+
verified: false,
|
|
1714
|
+
key: null
|
|
1715
|
+
};
|
|
1676
1716
|
}
|
|
1677
1717
|
verified = true;
|
|
1678
|
-
return
|
|
1718
|
+
return {
|
|
1719
|
+
verified: true,
|
|
1720
|
+
key
|
|
1721
|
+
};
|
|
1679
1722
|
} catch (error) {
|
|
1680
1723
|
threw = true;
|
|
1681
1724
|
span.setStatus({
|
|
@@ -1706,4 +1749,4 @@ async function hashJsonLd(jsonLd, contextLoader) {
|
|
|
1706
1749
|
return encodeHex(await crypto.subtle.digest("SHA-256", encoder.encode(canon)));
|
|
1707
1750
|
}
|
|
1708
1751
|
//#endregion
|
|
1709
|
-
export {
|
|
1752
|
+
export { fetchKey as C, validateCryptoKey as D, importJwk as E, verifyKeyOwnership as O, fetchActorDocument as S, generateCryptoKeyPair as T, verifyJsonLd as _, compactJsonLd as a, bypassKeyCacheReads as b, getNormalizationContextLoader as c, isClearlyMalformedContextReference as d, isInvalidUrlTypeError as f, verifyCompactJsonLdDetailed as g, verifyCompactJsonLd as h, attachSignature as i, hasSignature as l, signJsonLd as m, UnsafeJsonLdError as n, createSignature as o, markEffectiveContextLoader as p, assertSafeJsonLd as r, detachSignature as s, InvalidContextReferenceError as t, hasSignatureLike as u, verifySignature as v, fetchKeyDetailed as w, exportJwk as x, wrapContextLoaderForJsonLd as y };
|