@fedify/fedify 2.4.0-dev.2256 → 2.4.0-dev.2259
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-DvSQqk2l.mjs → builder-CBNa1Uw2.mjs} +8 -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-5bg_j_ye.mjs → compound-proof-CMPv4UK0.mjs} +20 -3
- package/dist/{context-CtI307_A.d.ts → context-7NyiqIcg.d.ts} +111 -2
- package/dist/{context-B6X-t8gI.d.cts → context-tsYPJ2Ew.d.cts} +111 -2
- package/dist/{deno-AmcRMq5z.mjs → deno-C8XaXmPB.mjs} +1 -1
- package/dist/{docloader-CIP_SG39.mjs → docloader-CpdFLwAg.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 +3 -3
- package/dist/federation/handler.test.mjs +76 -5
- package/dist/federation/hashlink-media.test.mjs +2 -2
- package/dist/federation/idempotency.test.mjs +2 -2
- package/dist/federation/inbox-report.test.d.mts +2 -0
- package/dist/federation/inbox-report.test.mjs +475 -0
- package/dist/federation/metrics.test.mjs +1 -1
- package/dist/federation/middleware.test.mjs +7 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +4 -3
- package/dist/federation/mod.d.ts +4 -3
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +5 -5
- 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 +4 -4
- package/dist/federation/portable-inbox.test.mjs +67 -6
- 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 +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-BDzIgqOd.cjs → federation-D6giSGUT.cjs} +524 -118
- package/dist/{http-DkqWu-sm.mjs → http-BqSbUEiQ.mjs} +141 -98
- package/dist/{http-1fZ83jj7.cjs → http-Cki-npuA.cjs} +447 -110
- package/dist/{http-BGb3QioZ.js → http-OMtKlbx1.js} +430 -111
- package/dist/{http-BrwKINQn.d.cts → key-C1nv7_jD.d.ts} +638 -229
- package/dist/{http-DGx0KOws.d.ts → key-DYxuyd-s.d.cts} +638 -229
- package/dist/{key-CEsu7oaD.mjs → key-DecAtABm.mjs} +30 -3
- package/dist/{kv-cache-CJS4mImS.mjs → kv-cache-CWWlMv-s.mjs} +1 -1
- package/dist/{kv-cache-BEWuZSB4.cjs → kv-cache-D73yVcE5.cjs} +1 -1
- package/dist/{kv-cache-CGhEgt98.js → kv-cache-J0v3UbUn.js} +1 -1
- package/dist/{ld-Cf4CPWN_.mjs → ld-UsN-TIPh.mjs} +40 -5
- package/dist/{metrics-CocsZP0E.mjs → metrics-DWCn4VXX.mjs} +2 -1
- package/dist/{middleware-BfYke3YQ.js → middleware-BqzfIlUO.js} +524 -118
- package/dist/{middleware-Dxn0E9ES.mjs → middleware-CkjwiEBd.mjs} +512 -127
- package/dist/{middleware-Cne_jMZo.mjs → middleware-DHn2q0L1.mjs} +1 -1
- package/dist/{mod-C7_2j7VT.d.cts → mod-BojP2Bw3.d.cts} +1 -1
- package/dist/{mod-BlLwewYe.d.ts → mod-CavhAgLw.d.cts} +5 -255
- package/dist/{mod-VHYh1lTK.d.cts → mod-CtpF2BU5.d.ts} +5 -255
- package/dist/{mod-B8MI1mpi.d.ts → mod-DEZXwV6J.d.ts} +1 -1
- package/dist/{mod-DFL6IxYQ.d.cts → mod-Dw-nPxQh.d.cts} +1 -1
- package/dist/{mod-BhTaDR5H.d.ts → mod-Xj5P4s4d.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +7 -7
- package/dist/mod.d.ts +7 -7
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-DSJ7nFgy.mjs → owner-CEBn81LD.mjs} +3 -3
- package/dist/{portable-collection-r-mHg1PV.cjs → portable-collection-DqTUBKY7.cjs} +1 -1
- package/dist/{portable-collection-BuBV6xTo.js → portable-collection-ZkUNjtb7.js} +1 -1
- package/dist/{portable-collection-qskqXJrH.mjs → portable-collection-qFSYw4TG.mjs} +2 -2
- package/dist/{portable-key-woGH_1nn.mjs → portable-key-LlMkP-vz.mjs} +1 -1
- package/dist/{proof-8WiH_-Gq.mjs → proof-BHRf_jMG.mjs} +133 -16
- package/dist/{send-JKzZBgPU.mjs → send-DjG8DDU_.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 +19 -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/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 +2 -2
- package/dist/sig/mod.d.ts +2 -2
- 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 +6 -6
- package/dist/sig/proof.test.mjs +76 -3
- 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.d.mts +2 -0
- package/dist/sig/verification.test.mjs +310 -0
- package/dist/{temporal-CT3fRaMH.mjs → temporal-BRFH_dte.mjs} +1 -1
- package/dist/testing/kv.test.mjs +1 -1
- package/dist/testing/mod.d.mts +315 -28
- 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/dist/verification-C3954hQh.mjs +5 -0
- package/dist/verification-Dpfcw8ml.mjs +105 -0
- package/package.json +7 -7
|
@@ -2,8 +2,9 @@ import { Temporal } from "temporal-polyfill";
|
|
|
2
2
|
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
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { a as verificationObservation } from "./verification-Dpfcw8ml.mjs";
|
|
6
|
+
import { n as version, t as name } from "./deno-C8XaXmPB.mjs";
|
|
7
|
+
import { _ as recordKeyLookup, n as getDurationMs, t as classifyFetchError } from "./metrics-DWCn4VXX.mjs";
|
|
7
8
|
import { n as attachKeyOwnerEvidence, t as MAX_PORTABLE_KEY_TTL } from "./key-owner-evidence-APB6NpSk.mjs";
|
|
8
9
|
import { getLogger } from "@logtape/logtape";
|
|
9
10
|
import { CryptographicKey, Multikey, Object as Object$1, isActor } from "@fedify/vocab";
|
|
@@ -898,12 +899,38 @@ async function fetchPortableActorKey(cacheKey, cls, options, onCachedUnavailable
|
|
|
898
899
|
};
|
|
899
900
|
}
|
|
900
901
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
901
|
-
return await fetchKeyWithResult(typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
902
|
+
return await fetchKeyWithResult(typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId, cls, options, async (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
903
|
+
const check = options[verificationObservation]?.check;
|
|
904
|
+
if (check != null) try {
|
|
905
|
+
const result = await _keyCache?.getFetchError?.(_cacheKey);
|
|
906
|
+
if (result != null) check.reason = {
|
|
907
|
+
type: "keyFetchError",
|
|
908
|
+
keyId: new URL(_cacheKey.href),
|
|
909
|
+
result
|
|
910
|
+
};
|
|
911
|
+
} catch {}
|
|
902
912
|
return {
|
|
903
913
|
key: null,
|
|
904
914
|
cached: true
|
|
905
915
|
};
|
|
906
916
|
}, async (error, cacheKey, keyId, keyCache, logger) => {
|
|
917
|
+
const check = options[verificationObservation]?.check;
|
|
918
|
+
if (check != null) {
|
|
919
|
+
let result;
|
|
920
|
+
try {
|
|
921
|
+
result = error instanceof FetchError && error.response != null ? {
|
|
922
|
+
status: error.response.status,
|
|
923
|
+
response: error.response.clone()
|
|
924
|
+
} : { error: error instanceof Error ? error : new Error(String(error)) };
|
|
925
|
+
} catch {
|
|
926
|
+
result = { error: error instanceof Error ? error : /* @__PURE__ */ new Error() };
|
|
927
|
+
}
|
|
928
|
+
check.reason = {
|
|
929
|
+
type: "keyFetchError",
|
|
930
|
+
keyId: new URL(cacheKey.href),
|
|
931
|
+
result
|
|
932
|
+
};
|
|
933
|
+
}
|
|
907
934
|
logger.debug("Failed to fetch key {keyId}.", {
|
|
908
935
|
keyId,
|
|
909
936
|
error
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { p as recordDocumentCache } from "./metrics-
|
|
4
|
+
import { p as recordDocumentCache } from "./metrics-DWCn4VXX.mjs";
|
|
5
5
|
import { getLogger } from "@logtape/logtape";
|
|
6
6
|
import { preloadedContexts } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/utils/kv-cache.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { URLPattern } = require("urlpattern-polyfill");
|
|
2
|
-
const require_http = require("./http-
|
|
2
|
+
const require_http = require("./http-Cki-npuA.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");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { URLPattern } from "urlpattern-polyfill";
|
|
3
|
-
import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-
|
|
3
|
+
import { G as validateCryptoKey, ot as recordDocumentCache, t as doubleKnock } from "./http-OMtKlbx1.js";
|
|
4
4
|
import { getLogger } from "@logtape/logtape";
|
|
5
5
|
import { FetchError, UrlError, createActivityPubRequest, getRemoteDocument, logRequest, preloadedContexts, resolveDocumentLoaderTimeout, validatePublicUrl, withDocumentLoaderTimeout } from "@fedify/vocab-runtime";
|
|
6
6
|
import { curry } from "es-toolkit";
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as
|
|
5
|
-
import { n as
|
|
6
|
-
import {
|
|
4
|
+
import { a as verificationObservation, i as triedKey, n as observeCheck, t as observeAttempt } from "./verification-Dpfcw8ml.mjs";
|
|
5
|
+
import { n as version, t as name } from "./deno-C8XaXmPB.mjs";
|
|
6
|
+
import { n as getDurationMs, r as getFederationMetrics, s as measureSignatureKeyFetch } from "./metrics-DWCn4VXX.mjs";
|
|
7
|
+
import { c as validateCryptoKey, i as fetchKey, t as bypassKeyCacheReads } from "./key-DecAtABm.mjs";
|
|
7
8
|
import { getLogger } from "@logtape/logtape";
|
|
8
9
|
import { Activity, CryptographicKey, Object as Object$1, getTypeId } from "@fedify/vocab";
|
|
9
10
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
@@ -450,6 +451,13 @@ function detachSignature(jsonLd) {
|
|
|
450
451
|
*/
|
|
451
452
|
async function verifySignature(jsonLd, options = {}) {
|
|
452
453
|
if (!hasSignature(jsonLd)) return null;
|
|
454
|
+
if (options[verificationObservation]?.attempt != null && options[verificationObservation]?.check == null) {
|
|
455
|
+
const declared = getLdSignatureObject(jsonLd)?.creator;
|
|
456
|
+
return await observeCheck(options, { mechanism: "linkedData" }, typeof declared === "string" ? declared : null, (observation) => verifySignature(jsonLd, {
|
|
457
|
+
...options,
|
|
458
|
+
[verificationObservation]: observation
|
|
459
|
+
}));
|
|
460
|
+
}
|
|
453
461
|
const sig = jsonLd.signature;
|
|
454
462
|
let signature;
|
|
455
463
|
try {
|
|
@@ -495,6 +503,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
495
503
|
const encoder = new TextEncoder();
|
|
496
504
|
const message = sigOptsHash + docHash;
|
|
497
505
|
const messageBytes = encoder.encode(message);
|
|
506
|
+
triedKey(options, key);
|
|
498
507
|
if (await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, signature.slice(), messageBytes)) return key;
|
|
499
508
|
if (cached) {
|
|
500
509
|
logger.debug("Failed to verify with the cached key {keyId}; signature {signatureValue} is invalid. Retrying with the freshly fetched key...", {
|
|
@@ -506,6 +515,7 @@ async function verifySignature(jsonLd, options = {}) {
|
|
|
506
515
|
keyCache: bypassKeyCacheReads(options.keyCache)
|
|
507
516
|
}));
|
|
508
517
|
if (key == null) return null;
|
|
518
|
+
triedKey(options, key);
|
|
509
519
|
return await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key.publicKey, signature.slice(), messageBytes) ? key : null;
|
|
510
520
|
}
|
|
511
521
|
logger.debug("Failed to verify with the fetched key {keyId}; signature {signatureValue} is invalid. Check if the key is correct or if the signed message is correct. The message to sign is:\n{message}", {
|
|
@@ -559,6 +569,14 @@ async function verifyCompactJsonLd(jsonLd, options = {}) {
|
|
|
559
569
|
return await verifyJsonLdInternal(jsonLd, options, false);
|
|
560
570
|
}
|
|
561
571
|
async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
572
|
+
if (options[verificationObservation]?.attempt == null) return await observeAttempt({
|
|
573
|
+
...options,
|
|
574
|
+
[verificationObservation]: options[verificationObservation] ?? { attempts: [] }
|
|
575
|
+
}, "linkedData", (observation) => verifyJsonLdInternal(jsonLd, {
|
|
576
|
+
...options,
|
|
577
|
+
[verificationObservation]: observation
|
|
578
|
+
}, compact), (value) => value);
|
|
579
|
+
const observation = options[verificationObservation];
|
|
562
580
|
return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("ld_signatures.verify", async (span) => {
|
|
563
581
|
const start = performance.now();
|
|
564
582
|
let verified = false;
|
|
@@ -571,6 +589,8 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
571
589
|
} : options;
|
|
572
590
|
const compacted = compact ? hasSignature(jsonLd) ? await compactJsonLd(jsonLd, options.contextLoader) : jsonLd : jsonLd;
|
|
573
591
|
const object = await Object$1.fromJsonLd(compacted, verificationOptions);
|
|
592
|
+
observation?.parsedObject?.(object);
|
|
593
|
+
if (observation?.subject != null) observation.subject.id = object.id == null ? null : new URL(object.id.href);
|
|
574
594
|
if (object.id != null) span.setAttribute("activitypub.object.id", object.id.href);
|
|
575
595
|
span.setAttribute("activitypub.object.type", getTypeId(object).href);
|
|
576
596
|
const sig = getLdSignatureObject(jsonLd);
|
|
@@ -585,13 +605,21 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
585
605
|
const attributions = new Set(object.attributionIds.map((uri) => uri.href));
|
|
586
606
|
if (object instanceof Activity) for (const uri of object.actorIds) attributions.add(uri.href);
|
|
587
607
|
const key = await verifySignature(compacted, verificationOptions);
|
|
588
|
-
if (key == null)
|
|
608
|
+
if (key == null) {
|
|
609
|
+
if (observation?.attempt != null && !hasLdSignatureProperty(jsonLd)) observation.attempt.reason = { type: "noSignature" };
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
589
612
|
if (key.ownerId == null) {
|
|
613
|
+
if (observation?.attempt != null) observation.attempt.reason = { type: "missingOwner" };
|
|
590
614
|
logger.debug("Key {keyId} has no owner.", { keyId: key.id?.href });
|
|
591
615
|
return false;
|
|
592
616
|
}
|
|
593
617
|
attributions.delete(key.ownerId.href);
|
|
594
618
|
if (attributions.size > 0) {
|
|
619
|
+
if (observation?.attempt != null) observation.attempt.reason = {
|
|
620
|
+
type: "uncoveredAttribution",
|
|
621
|
+
attributionIds: [...attributions].map((id) => new URL(id))
|
|
622
|
+
};
|
|
595
623
|
logger.debug("Some attributions are not authenticated by the Linked Data Signatures: {attributions}.", { attributions: [...attributions] });
|
|
596
624
|
return false;
|
|
597
625
|
}
|
|
@@ -605,8 +633,15 @@ async function verifyJsonLdInternal(jsonLd, options, compact) {
|
|
|
605
633
|
});
|
|
606
634
|
throw error;
|
|
607
635
|
} finally {
|
|
636
|
+
if (observation?.attempt?.reason != null) {
|
|
637
|
+
span.setAttribute("activitypub.verification.failure_reason", observation.attempt.reason.type);
|
|
638
|
+
span.setStatus({ code: SpanStatusCode.ERROR });
|
|
639
|
+
}
|
|
608
640
|
const classified = threw ? "error" : verified ? "verified" : hasLdSignatureProperty(jsonLd) ? "rejected" : "missing";
|
|
609
|
-
getFederationMetrics(options.meterProvider).recordSignatureVerificationDuration(getDurationMs(start), "linked_data", classified, {
|
|
641
|
+
getFederationMetrics(options.meterProvider).recordSignatureVerificationDuration(getDurationMs(start), "linked_data", classified, {
|
|
642
|
+
ldType: signatureType,
|
|
643
|
+
verificationFailureReason: verified || threw ? void 0 : observation?.attempt?.reason?.type ?? (hasLdSignatureProperty(jsonLd) ? "signatureVerificationFailed" : "noSignature")
|
|
644
|
+
});
|
|
610
645
|
span.end();
|
|
611
646
|
}
|
|
612
647
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
import "urlpattern-polyfill";
|
|
3
3
|
globalThis.addEventListener = () => {};
|
|
4
|
-
import { n as version, t as name } from "./deno-
|
|
4
|
+
import { n as version, t as name } from "./deno-C8XaXmPB.mjs";
|
|
5
5
|
import { metrics } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError } from "@fedify/vocab-runtime";
|
|
7
7
|
//#region src/federation/metrics.ts
|
|
@@ -302,6 +302,7 @@ var FederationMetrics = class {
|
|
|
302
302
|
};
|
|
303
303
|
if (extra.algorithm != null) attributes["http_signatures.algorithm"] = extra.algorithm;
|
|
304
304
|
if (extra.failureReason != null) attributes["http_signatures.failure_reason"] = extra.failureReason;
|
|
305
|
+
if (extra.verificationFailureReason != null) attributes["activitypub.verification.failure_reason"] = extra.verificationFailureReason;
|
|
305
306
|
if (extra.ldType != null) attributes["ld_signatures.type"] = extra.ldType;
|
|
306
307
|
if (extra.cryptosuite != null) attributes["object_integrity_proofs.cryptosuite"] = extra.cryptosuite;
|
|
307
308
|
this.signatureVerificationDuration.record(durationMs, attributes);
|