@fedify/fedify 2.4.0-dev.2127 → 2.4.0-dev.2129
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-B2bgGYbP.mjs → builder-C0bxZDL0.mjs} +3 -3
- 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-SVlHSzV7.mjs → compound-proof-D9Kljk_7.mjs} +3 -3
- package/dist/{context-Ci5vuUr_.d.ts → context-Cz1w5Krc.d.ts} +1 -1
- package/dist/{context-Bm6ldGvx.d.cts → context-Dvec_D_h.d.cts} +1 -1
- package/dist/{deno-Be9xoxps.mjs → deno-_o3lkDlG.mjs} +1 -1
- package/dist/{docloader-Dtuyb0ps.mjs → docloader-BbS0rO-Y.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 +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 +7 -7
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/outgoing-proof.test.mjs +6 -6
- package/dist/federation/portable-actor.test.mjs +3 -3
- package/dist/federation/portable-chain.test.mjs +3 -3
- package/dist/federation/portable-gateway-keys.test.mjs +76 -5
- package/dist/federation/portable-inbox.test.mjs +9 -4
- 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-B6IHuS6n.cjs → federation-DRY8KrkB.cjs} +12 -12
- package/dist/{http-o8l4QeUY.cjs → http-B1J6E-bT.cjs} +384 -33
- package/dist/{http-BFeK9sBg.mjs → http-BpOiZE09.mjs} +18 -12
- package/dist/{http-D76Py0M4.d.cts → http-C-x_OLSp.d.ts} +57 -14
- package/dist/{http-Rmbiu-5S.js → http-C2M6wcs8.js} +374 -35
- package/dist/{http-BrQgkJay.d.ts → http-CjezPjFX.d.cts} +57 -14
- package/dist/{key-Cc1b6pW9.mjs → key-DolJjJab.mjs} +103 -16
- package/dist/{kv-cache-tLKBfxHc.mjs → kv-cache-Bq2cah0c.mjs} +1 -1
- package/dist/{kv-cache-BweDce2I.js → kv-cache-D7TiyMxv.js} +1 -1
- package/dist/{kv-cache-BUkgZAcX.cjs → kv-cache-D9nRbG2Q.cjs} +1 -1
- package/dist/{ld-DQNTIrAe.mjs → ld-Dwc176V4.mjs} +3 -3
- package/dist/{metrics-DDE9S63Q.mjs → metrics-CDaHfBXY.mjs} +1 -1
- package/dist/{middleware-CsQorLC_.mjs → middleware-CmB1FD8A.mjs} +1 -1
- package/dist/{middleware-K9aLnf57.js → middleware-CylX-pvI.js} +12 -12
- package/dist/{middleware-BdhvduR9.mjs → middleware-DN3MdTDg.mjs} +24 -24
- package/dist/{mod-Co53r-VP.d.ts → mod-Bz9tFXI2.d.ts} +1 -1
- package/dist/{mod-Cwdt_CWU.d.ts → mod-CZetqT5h.d.ts} +1 -1
- package/dist/{mod-Cr79cQlc.d.cts → mod-D4g9ffEn.d.cts} +1 -1
- package/dist/{mod-AVir5nVI.d.cts → mod-DGOIxEfb.d.cts} +1 -1
- package/dist/{mod-Byt5tvAS.d.cts → mod-S--JxYjo.d.cts} +1 -1
- package/dist/{mod-eVOUPbQE.d.ts → mod-owwElvpw.d.ts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +5 -5
- package/dist/mod.d.ts +5 -5
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/handler.test.mjs +1 -1
- package/dist/{owner-CCfdL83M.mjs → owner-BNHhwjNu.mjs} +37 -4
- package/dist/{portable-collection-WXaHkNqC.mjs → portable-collection-CRpTUHCY.mjs} +2 -2
- package/dist/{portable-collection-DdXsKBg4.js → portable-collection-CgglAI9B.js} +34 -1
- package/dist/{portable-collection-DXogVs__.cjs → portable-collection-PTGD0q70.cjs} +34 -1
- package/dist/portable-key-DqX2emHQ.mjs +395 -0
- package/dist/{portable-key-id-T7lecIbt.mjs → portable-key-id-Bg259c4Z.mjs} +69 -2
- package/dist/{proof-CW8k0R1G.mjs → proof-B4_0E-KU.mjs} +5 -5
- package/dist/{send--FORaIc4.mjs → send-Dpu5qbP5.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.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-key.test.mjs +479 -5
- package/dist/sig/proof.test.mjs +3 -3
- package/dist/{temporal-CffY_XOJ.mjs → temporal-78JVR3GK.mjs} +1 -1
- package/dist/testing/kv.test.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.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/portable-key-C-fPq_Yf.mjs +0 -214
|
@@ -4,7 +4,7 @@ import { getLogger } from "@logtape/logtape";
|
|
|
4
4
|
import { Activity, CryptographicKey, DataIntegrityProof, Multikey, Object as Object$1, PUBLIC_COLLECTION, getTypeId, isActor } from "@fedify/vocab";
|
|
5
5
|
import { SpanKind, SpanStatusCode, metrics, trace } from "@opentelemetry/api";
|
|
6
6
|
import { FetchError, canonicalizePortableUri, encodeMultibase, formatIri, fromCompatibleEf61Id, getDocumentLoader, getFe34Origin, isGatewayUrl, parseDidKeyVerificationMethod, parseIri, preloadedContexts, toCompatibleEf61Id } from "@fedify/vocab-runtime";
|
|
7
|
-
import { isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
7
|
+
import { getPortableGatewayCandidates, isCompatibleEf61Iri } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
8
8
|
import { encodeHex } from "byte-encodings/hex";
|
|
9
9
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
10
10
|
import { Item, decodeDict, encodeDict, encodeItem } from "structured-field-values";
|
|
@@ -14,10 +14,12 @@ import serialize from "json-canon";
|
|
|
14
14
|
import { ATTR_HTTP_REQUEST_HEADER, ATTR_HTTP_REQUEST_METHOD, ATTR_URL_FULL } from "@opentelemetry/semantic-conventions";
|
|
15
15
|
//#region deno.json
|
|
16
16
|
var name = "@fedify/fedify";
|
|
17
|
-
var version = "2.4.0-dev.
|
|
17
|
+
var version = "2.4.0-dev.2129+c0ddb433";
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/sig/portable-key-id.ts
|
|
20
20
|
const COMPATIBLE_KEY_ID_PATH_PATTERN = /^\/\.well-known\/apgateway\/did(?::|%3A)/i;
|
|
21
|
+
const RAW_PORTABLE_URI_PATTERN = /^ap(?:\+ef61)?:\/\//i;
|
|
22
|
+
const RAW_COMPATIBLE_ID_PREFIX_PATTERN = /^https?:\/\/[^/?#]*\/\.well-known\/apgateway\/(?=did(?::|%3A))/i;
|
|
21
23
|
/**
|
|
22
24
|
* Checks whether the URL is an `ap:` or `ap+ef61:` URI.
|
|
23
25
|
* @internal
|
|
@@ -81,6 +83,20 @@ function isCompatibleKeyId(keyId) {
|
|
|
81
83
|
return (keyId.protocol === "http:" || keyId.protocol === "https:") && COMPATIBLE_KEY_ID_PATH_PATTERN.test(keyId.pathname);
|
|
82
84
|
}
|
|
83
85
|
/**
|
|
86
|
+
* Checks whether a key ID may name a key that is valid only for HTTP
|
|
87
|
+
* Signatures: a gateway key at an [FEP-ef61] compatible identifier, or a key
|
|
88
|
+
* of a portable actor at an `ap:` or `ap+ef61:` URI. Neither ever makes or
|
|
89
|
+
* verifies an Object Integrity Proof or a Linked Data Signature: a portable
|
|
90
|
+
* object's proof is made by its DID, and a proof made with a gateway key
|
|
91
|
+
* would claim that the gateway authored the object.
|
|
92
|
+
*
|
|
93
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
94
|
+
* @internal
|
|
95
|
+
*/
|
|
96
|
+
function isPortableKeyId(keyId) {
|
|
97
|
+
return isPortableUri(keyId) || isCompatibleKeyId(keyId);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
84
100
|
* Gets the canonical portable ID of an actor ID that is either an `ap:` or
|
|
85
101
|
* `ap+ef61:` URI or a compatible identifier.
|
|
86
102
|
* @returns The canonical portable ID, or `null` if the ID is neither, or is
|
|
@@ -99,6 +115,57 @@ function getCanonicalPortableId(id) {
|
|
|
99
115
|
}
|
|
100
116
|
}
|
|
101
117
|
/**
|
|
118
|
+
* Gets the canonical portable ID of an `ap:` or `ap+ef61:` URI or
|
|
119
|
+
* a compatible identifier as it is written, before any URL parsing.
|
|
120
|
+
* Parsing an ID into a `URL` resolves dot segments in its path, which would
|
|
121
|
+
* make it identify another portable object, e.g.,
|
|
122
|
+
* `ap://did:key:z6Mk…/x/../actor` would become `ap://did:key:z6Mk…/actor`.
|
|
123
|
+
* Such an ID has no canonical portable ID here.
|
|
124
|
+
* @param raw The ID as it is written.
|
|
125
|
+
* @returns The canonical portable ID, fragment included, or `null` if the ID
|
|
126
|
+
* is neither an `ap:` or `ap+ef61:` URI nor a compatible identifier,
|
|
127
|
+
* is malformed, or would identify another object once parsed.
|
|
128
|
+
* @internal
|
|
129
|
+
*/
|
|
130
|
+
function getRawCanonicalPortableId(raw) {
|
|
131
|
+
let canonical;
|
|
132
|
+
let parsed;
|
|
133
|
+
try {
|
|
134
|
+
if (RAW_PORTABLE_URI_PATTERN.test(raw)) {
|
|
135
|
+
canonical = canonicalizePortableUri(raw);
|
|
136
|
+
parsed = canonicalizePortableUri(formatIri(parseIri(raw)));
|
|
137
|
+
} else {
|
|
138
|
+
const prefix = raw.match(RAW_COMPATIBLE_ID_PREFIX_PATTERN);
|
|
139
|
+
if (prefix == null || !URL.canParse(raw)) return null;
|
|
140
|
+
canonical = canonicalizePortableUri("ap://" + raw.slice(prefix[0].length));
|
|
141
|
+
parsed = getCanonicalPortableId(new URL(raw));
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof TypeError) return null;
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
return canonical === parsed ? canonical : null;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Parses a key ID, e.g., the `keyId` of an HTTP Signature, into a `URL`.
|
|
151
|
+
* An `ap:` or `ap+ef61:` key ID is parsed into the internal `URL` form of
|
|
152
|
+
* portable URIs. A portable or compatible key ID that is malformed, or
|
|
153
|
+
* whose identity URL parsing would change, e.g., by resolving dot segments in
|
|
154
|
+
* its path, is refused, so that it can never be taken for, or looked up in
|
|
155
|
+
* the key cache as, the key of another object.
|
|
156
|
+
* @param raw The key ID as it is written.
|
|
157
|
+
* @returns The parsed key ID, or `null` if it is invalid.
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
function parseKeyIdString(raw) {
|
|
161
|
+
if (RAW_PORTABLE_URI_PATTERN.test(raw)) return getRawCanonicalPortableId(raw) == null ? null : parseIri(raw);
|
|
162
|
+
if (!URL.canParse(raw)) return null;
|
|
163
|
+
const url = new URL(raw);
|
|
164
|
+
if (isPortableUri(url)) return null;
|
|
165
|
+
if (!RAW_COMPATIBLE_ID_PREFIX_PATTERN.test(raw)) return isCompatibleKeyId(url) ? null : url;
|
|
166
|
+
return getRawCanonicalPortableId(raw) == null ? null : url;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
102
169
|
* Builds the base of the key IDs of a gateway's keys for a portable actor:
|
|
103
170
|
* the actor's compatible identifier on the gateway.
|
|
104
171
|
* @param actorId The portable actor's ID, either an `ap:` or `ap+ef61:` URI
|
|
@@ -1342,6 +1409,17 @@ function bypassKeyCacheReads(keyCache) {
|
|
|
1342
1409
|
};
|
|
1343
1410
|
return bypassed;
|
|
1344
1411
|
}
|
|
1412
|
+
/**
|
|
1413
|
+
* Parses a key ID given as a string. Unlike `new URL()`, it accepts `ap:`
|
|
1414
|
+
* and `ap+ef61:` URIs, and refuses a portable or compatible key ID whose
|
|
1415
|
+
* identity URL parsing would change, e.g., by resolving dot segments.
|
|
1416
|
+
* @throws {TypeError} If the key ID is invalid.
|
|
1417
|
+
*/
|
|
1418
|
+
function parseKeyIdOrThrow(keyId) {
|
|
1419
|
+
const parsed = parseKeyIdString(keyId);
|
|
1420
|
+
if (parsed == null) throw new TypeError(`Invalid key ID: ${keyId}`);
|
|
1421
|
+
return parsed;
|
|
1422
|
+
}
|
|
1345
1423
|
async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
1346
1424
|
tracerProvider ??= trace.getTracerProvider();
|
|
1347
1425
|
return await tracerProvider.getTracer(name, version).startActiveSpan("activitypub.fetch_key", {
|
|
@@ -1378,9 +1456,11 @@ async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
|
1378
1456
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
1379
1457
|
* compatible identifiers that dereference to portable actor documents, are
|
|
1380
1458
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
1381
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
1382
|
-
*
|
|
1383
|
-
*
|
|
1459
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
1460
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
1461
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
1462
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
1463
|
+
* except for failures to fetch them.
|
|
1384
1464
|
*
|
|
1385
1465
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
1386
1466
|
* @template T The type of the key to fetch. Either {@link CryptographicKey}
|
|
@@ -1393,7 +1473,7 @@ async function withFetchKeySpan(keyId, tracerProvider, fetcher) {
|
|
|
1393
1473
|
* @since 1.3.0
|
|
1394
1474
|
*/
|
|
1395
1475
|
function fetchKey(keyId, cls, options = {}) {
|
|
1396
|
-
keyId = typeof keyId === "string" ?
|
|
1476
|
+
keyId = typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId;
|
|
1397
1477
|
return withFetchKeySpan(keyId, options.tracerProvider, () => fetchKeyInternal(keyId, cls, options));
|
|
1398
1478
|
}
|
|
1399
1479
|
/**
|
|
@@ -1403,9 +1483,11 @@ function fetchKey(keyId, cls, options = {}) {
|
|
|
1403
1483
|
* Gateway keys of [FEP-ef61] portable actors, i.e., keys whose IDs are
|
|
1404
1484
|
* compatible identifiers that dereference to portable actor documents, are
|
|
1405
1485
|
* not resolved by this function, as they only authenticate HTTP requests;
|
|
1406
|
-
* use `verifyRequest()` or `getKeyOwner()` for them instead.
|
|
1407
|
-
*
|
|
1408
|
-
*
|
|
1486
|
+
* use `verifyRequest()` or `getKeyOwner()` for them instead. Nor are keys
|
|
1487
|
+
* of portable actors whose IDs are `ap:` or `ap+ef61:` URIs, for the same
|
|
1488
|
+
* reason. Keys whose IDs are compatible identifiers or `ap:` or `ap+ef61:`
|
|
1489
|
+
* URIs are never read from or written to the key cache under their IDs,
|
|
1490
|
+
* except for failures to fetch them.
|
|
1409
1491
|
*
|
|
1410
1492
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
1411
1493
|
*
|
|
@@ -1419,7 +1501,7 @@ function fetchKey(keyId, cls, options = {}) {
|
|
|
1419
1501
|
* @since 2.1.0
|
|
1420
1502
|
*/
|
|
1421
1503
|
async function fetchKeyDetailed(keyId, cls, options = {}) {
|
|
1422
|
-
const cacheKey = typeof keyId === "string" ?
|
|
1504
|
+
const cacheKey = typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId;
|
|
1423
1505
|
return await withFetchKeySpan(cacheKey, options.tracerProvider, async () => {
|
|
1424
1506
|
return await fetchKeyWithResult(cacheKey, cls, options, async (cacheKey, keyId, keyCache, logger) => {
|
|
1425
1507
|
const fetchError = await keyCache?.getFetchError?.(cacheKey);
|
|
@@ -1558,7 +1640,7 @@ async function resolveDidKey(cacheKey, cls, keyCache, logger) {
|
|
|
1558
1640
|
cached: false
|
|
1559
1641
|
};
|
|
1560
1642
|
}
|
|
1561
|
-
async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider, keyIdBoundByCaller,
|
|
1643
|
+
async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, { documentLoader, contextLoader, keyCache, tracerProvider, keyIdBoundByCaller, portableKeyResolvers }, logger) {
|
|
1562
1644
|
let object;
|
|
1563
1645
|
try {
|
|
1564
1646
|
object = await Object$1.fromJsonLd(document, {
|
|
@@ -1589,7 +1671,7 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
|
|
|
1589
1671
|
}
|
|
1590
1672
|
if (isCompatibleKeyId(cacheKey) && isPortableActorDocument(object)) {
|
|
1591
1673
|
const scopedCache = keyCache;
|
|
1592
|
-
if (
|
|
1674
|
+
if (portableKeyResolvers == null || cls !== CryptographicKey) {
|
|
1593
1675
|
logger.debug("Failed to verify; key {keyId} is a gateway key of the portable actor {actorId}, which is only accepted for HTTP Signatures.", {
|
|
1594
1676
|
keyId,
|
|
1595
1677
|
actorId: object.id?.href
|
|
@@ -1600,7 +1682,7 @@ async function resolveFetchedKey(document, cacheKey, documentUrl, keyId, cls, {
|
|
|
1600
1682
|
cached: false
|
|
1601
1683
|
};
|
|
1602
1684
|
}
|
|
1603
|
-
const resolution = await
|
|
1685
|
+
const resolution = await portableKeyResolvers.gatewayKey(document, object, cacheKey);
|
|
1604
1686
|
if (resolution.type !== "verified") {
|
|
1605
1687
|
logger.debug("Failed to verify; the portable actor {actorId} does not vouch for its gateway key {keyId}.", {
|
|
1606
1688
|
keyId,
|
|
@@ -1760,6 +1842,11 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
1760
1842
|
]);
|
|
1761
1843
|
const keyId = cacheKey.href;
|
|
1762
1844
|
const keyCache = options.keyCache;
|
|
1845
|
+
if (isPortableUri(cacheKey)) {
|
|
1846
|
+
const result = await fetchPortableActorKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger);
|
|
1847
|
+
outcome = result.outcome;
|
|
1848
|
+
return result.result;
|
|
1849
|
+
}
|
|
1763
1850
|
if (isCompatibleKeyId(cacheKey)) {
|
|
1764
1851
|
const result = await fetchCompatibleKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger);
|
|
1765
1852
|
outcome = result.outcome;
|
|
@@ -1811,7 +1898,7 @@ async function fetchKeyWithResult(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
1811
1898
|
*/
|
|
1812
1899
|
function getCompatibleKeyScope(cls, options) {
|
|
1813
1900
|
if (cls !== CryptographicKey) return "multikey";
|
|
1814
|
-
return options.
|
|
1901
|
+
return options.portableKeyResolvers == null ? "cryptographicKey" : "httpSignature";
|
|
1815
1902
|
}
|
|
1816
1903
|
/**
|
|
1817
1904
|
* Looks up a key at an [FEP-ef61] compatible identifier. Such a key may be
|
|
@@ -1865,8 +1952,75 @@ async function fetchCompatibleKey(cacheKey, cls, options, onCachedUnavailable, o
|
|
|
1865
1952
|
outcome: { result: resolved.key != null ? "fetched" : "invalid" }
|
|
1866
1953
|
};
|
|
1867
1954
|
}
|
|
1955
|
+
/**
|
|
1956
|
+
* Looks up a key of an [FEP-ef61] portable actor at an `ap:` or `ap+ef61:`
|
|
1957
|
+
* key ID. Such a key is accepted only for HTTP Signatures, and is rejected
|
|
1958
|
+
* for any other purpose without being fetched. Like keys at compatible
|
|
1959
|
+
* identifiers, what it resolves to is cached in the namespace of the lookup's
|
|
1960
|
+
* purpose, and a failure to fetch the actor's document from every gateway is
|
|
1961
|
+
* cached in the shared namespace. A failure that is neither, e.g., one
|
|
1962
|
+
* gateway being unreachable while another served an invalid document, is not
|
|
1963
|
+
* cached at all.
|
|
1964
|
+
*
|
|
1965
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
1966
|
+
*/
|
|
1967
|
+
async function fetchPortableActorKey(cacheKey, cls, options, onCachedUnavailable, onFetchError, logger) {
|
|
1968
|
+
const keyId = cacheKey.href;
|
|
1969
|
+
const resolvers = options.portableKeyResolvers;
|
|
1970
|
+
if (resolvers == null || cls !== CryptographicKey) {
|
|
1971
|
+
logger.debug("Failed to verify; key {keyId} is a key of a portable actor, which is only accepted for HTTP Signatures.", { keyId });
|
|
1972
|
+
return {
|
|
1973
|
+
result: {
|
|
1974
|
+
key: null,
|
|
1975
|
+
cached: false
|
|
1976
|
+
},
|
|
1977
|
+
outcome: { result: "invalid" }
|
|
1978
|
+
};
|
|
1979
|
+
}
|
|
1980
|
+
const sharedCache = options.keyCache;
|
|
1981
|
+
const scopedCache = sharedCache?.compatibleKeyScope?.("httpSignature");
|
|
1982
|
+
const cached = await getCachedFetchKey(cacheKey, keyId, cls, scopedCache, logger);
|
|
1983
|
+
if (cached != null) return {
|
|
1984
|
+
result: cached,
|
|
1985
|
+
outcome: { result: "hit" }
|
|
1986
|
+
};
|
|
1987
|
+
if (await sharedCache?.get(cacheKey) === null) {
|
|
1988
|
+
logger.debug("Entry {keyId} found in cache, but it could not be fetched.", { keyId });
|
|
1989
|
+
return {
|
|
1990
|
+
result: await onCachedUnavailable(cacheKey, keyId, sharedCache, logger),
|
|
1991
|
+
outcome: { result: "hit" }
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1994
|
+
logger.debug("Resolving key {keyId} to verify signature...", { keyId });
|
|
1995
|
+
const resolution = await resolvers.actorKey(cacheKey);
|
|
1996
|
+
if (resolution.type === "verified") {
|
|
1997
|
+
await scopedCache?.set(cacheKey, resolution.key, { expires: resolution.expires });
|
|
1998
|
+
return {
|
|
1999
|
+
result: {
|
|
2000
|
+
key: resolution.key,
|
|
2001
|
+
cached: false
|
|
2002
|
+
},
|
|
2003
|
+
outcome: { result: "fetched" }
|
|
2004
|
+
};
|
|
2005
|
+
}
|
|
2006
|
+
if (resolution.type === "rejected") {
|
|
2007
|
+
await scopedCache?.set(cacheKey, null);
|
|
2008
|
+
return {
|
|
2009
|
+
result: {
|
|
2010
|
+
key: null,
|
|
2011
|
+
cached: false
|
|
2012
|
+
},
|
|
2013
|
+
outcome: { result: "invalid" }
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
await scopedCache?.delete(cacheKey);
|
|
2017
|
+
return {
|
|
2018
|
+
result: await onFetchError(resolution.error, cacheKey, keyId, resolution.cacheable ? sharedCache : void 0, logger),
|
|
2019
|
+
outcome: resolution.cacheable ? classifyFetchError(resolution.error) : { result: "error" }
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
1868
2022
|
async function fetchKeyInternal(keyId, cls, options = {}) {
|
|
1869
|
-
return await fetchKeyWithResult(typeof keyId === "string" ?
|
|
2023
|
+
return await fetchKeyWithResult(typeof keyId === "string" ? parseKeyIdOrThrow(keyId) : keyId, cls, options, (_cacheKey, _keyId, _keyCache, _logger) => {
|
|
1870
2024
|
return {
|
|
1871
2025
|
key: null,
|
|
1872
2026
|
cached: true
|
|
@@ -4034,6 +4188,14 @@ const SEC = "https://w3id.org/security#";
|
|
|
4034
4188
|
* - no more than one entry of either property has that ID; and
|
|
4035
4189
|
* - the key ID's origin is one of the actor's `gateways`.
|
|
4036
4190
|
*
|
|
4191
|
+
* An entry has the key's ID if its ID is the key ID, or any compatible
|
|
4192
|
+
* identifier on the same gateway, or the `ap:` or `ap+ef61:` URI, with the
|
|
4193
|
+
* same canonical portable ID. Some publishers, e.g., Mitra, list the keys
|
|
4194
|
+
* of portable actors under `ap:` URIs, but sign requests with compatible key
|
|
4195
|
+
* IDs on their own gateways. IDs are compared as they are written in
|
|
4196
|
+
* the signed document, so an ID that URL parsing would turn into another,
|
|
4197
|
+
* e.g., by resolving dot segments, has no match.
|
|
4198
|
+
*
|
|
4037
4199
|
* [FEP-8b32]: https://w3id.org/fep/8b32
|
|
4038
4200
|
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
4039
4201
|
* [FEP-521a]: https://w3id.org/fep/521a
|
|
@@ -4045,10 +4207,22 @@ const SEC = "https://w3id.org/security#";
|
|
|
4045
4207
|
* @returns The verification result, which is never `legacy`.
|
|
4046
4208
|
* @internal
|
|
4047
4209
|
*/
|
|
4048
|
-
|
|
4210
|
+
function verifyPortableGatewayKeyDocument(document, actor, keyId, options = {}) {
|
|
4211
|
+
return verifyPortableKeyDocument(document, actor, keyId, true, options);
|
|
4212
|
+
}
|
|
4213
|
+
/**
|
|
4214
|
+
* Verifies that the signed document of a portable actor vouches for the key
|
|
4215
|
+
* with the given ID, either a gateway key at a compatible key ID, or a key of
|
|
4216
|
+
* the actor itself at an `ap:` or `ap+ef61:` key ID. See
|
|
4217
|
+
* {@link verifyPortableGatewayKeyDocument} for the rules; a key of the actor
|
|
4218
|
+
* itself names no gateway, so instead of the key ID's origin being one of
|
|
4219
|
+
* the actor's `gateways`, the actor only has to have a valid gateway, as
|
|
4220
|
+
* FEP-ef61 requires of every portable actor.
|
|
4221
|
+
*/
|
|
4222
|
+
async function verifyPortableKeyDocument(document, actor, keyId, isGatewayKey, options) {
|
|
4049
4223
|
const reject = (reason) => {
|
|
4050
|
-
logger.debug("Failed to verify
|
|
4051
|
-
keyId: keyId
|
|
4224
|
+
logger.debug("Failed to verify key {keyId} of the portable actor {actorId}: {reason}", {
|
|
4225
|
+
keyId: formatIri(keyId),
|
|
4052
4226
|
actorId: actor.id?.href,
|
|
4053
4227
|
reason
|
|
4054
4228
|
});
|
|
@@ -4060,8 +4234,9 @@ async function verifyPortableGatewayKeyDocument(document, actor, keyId, options
|
|
|
4060
4234
|
const keyBase = new URL(keyId.href);
|
|
4061
4235
|
keyBase.hash = "";
|
|
4062
4236
|
const claimedActorId = getCanonicalPortableId(keyBase);
|
|
4237
|
+
const claimedKeyId = getCanonicalPortableId(keyId);
|
|
4063
4238
|
const actorId = actor.id == null ? null : getCanonicalPortableId(actor.id);
|
|
4064
|
-
if (claimedActorId == null || actorId == null) return reject("The key ID or the actor ID is not a valid portable ID.");
|
|
4239
|
+
if (claimedActorId == null || claimedKeyId == null || actorId == null) return reject("The key ID or the actor ID is not a valid portable ID.");
|
|
4065
4240
|
if (claimedActorId !== actorId) return reject("The key ID is not a compatible identifier of the actor it dereferences to.");
|
|
4066
4241
|
let verification;
|
|
4067
4242
|
try {
|
|
@@ -4106,10 +4281,12 @@ async function verifyPortableGatewayKeyDocument(document, actor, keyId, options
|
|
|
4106
4281
|
if (!(error instanceof TypeError)) throw error;
|
|
4107
4282
|
return reject("The verified actor document is malformed.");
|
|
4108
4283
|
}
|
|
4109
|
-
|
|
4284
|
+
const rootId = root["@id"];
|
|
4285
|
+
if (!isPortableActorDocument(verifiedActor) || getCanonicalPortableId(verifiedActor.id) !== claimedActorId || typeof rootId !== "string" || getRawCanonicalPortableId(rootId) !== claimedActorId) return reject("The key ID is not a compatible identifier of the actor whose document is signed.");
|
|
4110
4286
|
actor = verifiedActor;
|
|
4111
|
-
const
|
|
4112
|
-
const
|
|
4287
|
+
const findKeyNodes = (values) => findNodes(values, claimedKeyId, isGatewayKey ? keyId.origin : null);
|
|
4288
|
+
const assertionNodes = findKeyNodes(root[`${SEC}assertionMethod`]);
|
|
4289
|
+
const publicKeyNodes = findKeyNodes(root[`${SEC}publicKey`]);
|
|
4113
4290
|
if (assertionNodes.length > 1 || publicKeyNodes.length > 1) return reject("The actor document has more than one key with the ID.");
|
|
4114
4291
|
let publicKey;
|
|
4115
4292
|
if (assertionNodes.length > 0) {
|
|
@@ -4139,7 +4316,9 @@ async function verifyPortableGatewayKeyDocument(document, actor, keyId, options
|
|
|
4139
4316
|
if (embedded.ownerId == null || getCanonicalPortableId(embedded.ownerId) !== actorId) return reject("The owner of the key is not the actor.");
|
|
4140
4317
|
publicKey = embedded.publicKey;
|
|
4141
4318
|
}
|
|
4142
|
-
if (
|
|
4319
|
+
if (isGatewayKey) {
|
|
4320
|
+
if (!actor.gateways.some((gateway) => isGatewayUrl(gateway) && gateway.origin === keyId.origin)) return reject(`The gateway ${keyId.origin} is not listed in the actor's gateways.`);
|
|
4321
|
+
} else if (!actor.gateways.some(isGatewayUrl)) return reject("The actor has no valid gateways.");
|
|
4143
4322
|
const key = new CryptographicKey({
|
|
4144
4323
|
id: keyId,
|
|
4145
4324
|
owner: actor.id,
|
|
@@ -4194,15 +4373,170 @@ async function fetchPortableGatewayKey(keyId, options = {}) {
|
|
|
4194
4373
|
contextLoader
|
|
4195
4374
|
});
|
|
4196
4375
|
}
|
|
4197
|
-
|
|
4376
|
+
/**
|
|
4377
|
+
* Resolves a key of a portable actor at an `ap:` or `ap+ef61:` key ID, e.g.,
|
|
4378
|
+
* `ap://did:key:z6Mk…/actor#main-key`. Such a key ID names no gateway, so
|
|
4379
|
+
* the actor's document, i.e., the key ID without its fragment, is fetched
|
|
4380
|
+
* through the gateways in its `@gateway` location hints, one after another,
|
|
4381
|
+
* until one of them serves a document that vouches for the key. Without
|
|
4382
|
+
* location hints, the document loader is asked for the `ap:` URI itself,
|
|
4383
|
+
* which only a custom document loader can resolve. The hints are chosen by
|
|
4384
|
+
* whoever made the signature, but that does not matter: only a document with
|
|
4385
|
+
* a valid proof by the DID of the key ID vouches for the key.
|
|
4386
|
+
*
|
|
4387
|
+
* The key is taken as a key of the actor itself, not of a gateway, so it is
|
|
4388
|
+
* accepted by the rules of {@link verifyPortableGatewayKeyDocument}, except
|
|
4389
|
+
* that it is listed under the `ap:` or `ap+ef61:` URI with the same canonical
|
|
4390
|
+
* ID as the key ID, and that the actor only has to have a valid gateway.
|
|
4391
|
+
* The key ID must have a fragment; a key served as a standalone document is
|
|
4392
|
+
* not supported.
|
|
4393
|
+
*
|
|
4394
|
+
* If no gateway serves a document that vouches for the key, the result is
|
|
4395
|
+
* `rejected` only if every gateway served a document that definitely does not
|
|
4396
|
+
* vouch for it. If every gateway failed to serve a document at all, the
|
|
4397
|
+
* result is a cacheable `unavailable`, with the error of the first gateway if
|
|
4398
|
+
* every gateway responded with the same HTTP status, so that the status
|
|
4399
|
+
* describes the whole lookup. Otherwise, e.g., if one gateway was
|
|
4400
|
+
* unreachable and another served an invalid document, nothing tells what the
|
|
4401
|
+
* unreachable gateway would have served, so the result is an `unavailable`
|
|
4402
|
+
* that is not cacheable.
|
|
4403
|
+
*
|
|
4404
|
+
* @param keyId The key ID, which must be an `ap:` or `ap+ef61:` URI.
|
|
4405
|
+
* @param options Loaders and telemetry providers.
|
|
4406
|
+
* @returns The resolution, which is never `legacy`.
|
|
4407
|
+
* @internal
|
|
4408
|
+
*/
|
|
4409
|
+
async function resolvePortableActorKey(keyId, options = {}) {
|
|
4410
|
+
const documentLoader = options.documentLoader ?? getDocumentLoader();
|
|
4411
|
+
const contextLoader = options.contextLoader ?? getDocumentLoader();
|
|
4412
|
+
let formattedKeyId = keyId.href;
|
|
4413
|
+
const reject = (reason) => {
|
|
4414
|
+
logger.debug("Failed to verify key {keyId} of a portable actor: {reason}", {
|
|
4415
|
+
keyId: formattedKeyId,
|
|
4416
|
+
reason
|
|
4417
|
+
});
|
|
4418
|
+
return {
|
|
4419
|
+
type: "rejected",
|
|
4420
|
+
reason
|
|
4421
|
+
};
|
|
4422
|
+
};
|
|
4423
|
+
if (!isPortableUri(keyId) || getCanonicalPortableId(keyId) == null) return reject("The key ID is not a valid ap: or ap+ef61: URI.");
|
|
4424
|
+
formattedKeyId = formatIri(keyId);
|
|
4425
|
+
if (keyId.hash === "" || keyId.hash === "#") return reject("The key ID has no fragment; only keys embedded in actor documents are supported.");
|
|
4426
|
+
const actorUrl = new URL(keyId.href);
|
|
4427
|
+
actorUrl.hash = "";
|
|
4428
|
+
const requestUrls = [];
|
|
4429
|
+
for (const gateway of getPortableGatewayCandidates(actorUrl)) try {
|
|
4430
|
+
requestUrls.push(toCompatibleEf61Id(actorUrl, gateway).href);
|
|
4431
|
+
} catch (error) {
|
|
4432
|
+
if (!(error instanceof TypeError)) throw error;
|
|
4433
|
+
return reject(`The key ID cannot be fetched from gateways: ${error}`);
|
|
4434
|
+
}
|
|
4435
|
+
if (requestUrls.length < 1) requestUrls.push(formatIri(actorUrl));
|
|
4436
|
+
const attempts = [];
|
|
4437
|
+
for (const url of requestUrls) {
|
|
4438
|
+
let remoteDocument;
|
|
4439
|
+
try {
|
|
4440
|
+
remoteDocument = await documentLoader(url);
|
|
4441
|
+
} catch (error) {
|
|
4442
|
+
logger.debug("Failed to fetch the actor of key {keyId} from {url}: {error}", {
|
|
4443
|
+
keyId: formattedKeyId,
|
|
4444
|
+
url,
|
|
4445
|
+
error
|
|
4446
|
+
});
|
|
4447
|
+
attempts.push({
|
|
4448
|
+
type: "retrievalFailed",
|
|
4449
|
+
error
|
|
4450
|
+
});
|
|
4451
|
+
continue;
|
|
4452
|
+
}
|
|
4453
|
+
let resolution;
|
|
4454
|
+
try {
|
|
4455
|
+
const object = await Object$1.fromJsonLd(remoteDocument.document, {
|
|
4456
|
+
documentLoader,
|
|
4457
|
+
contextLoader,
|
|
4458
|
+
tracerProvider: options.tracerProvider
|
|
4459
|
+
});
|
|
4460
|
+
resolution = isPortableActorDocument(object) ? await verifyPortableKeyDocument(remoteDocument.document, object, keyId, false, {
|
|
4461
|
+
...options,
|
|
4462
|
+
documentLoader,
|
|
4463
|
+
contextLoader
|
|
4464
|
+
}) : {
|
|
4465
|
+
type: "rejected",
|
|
4466
|
+
reason: "The document is not a portable actor."
|
|
4467
|
+
};
|
|
4468
|
+
} catch (error) {
|
|
4469
|
+
if (error instanceof TypeError) resolution = {
|
|
4470
|
+
type: "rejected",
|
|
4471
|
+
reason: `The document is malformed: ${error.message}`
|
|
4472
|
+
};
|
|
4473
|
+
else {
|
|
4474
|
+
logger.debug("Failed to process the actor of key {keyId} served from {url}: {error}", {
|
|
4475
|
+
keyId: formattedKeyId,
|
|
4476
|
+
url,
|
|
4477
|
+
error
|
|
4478
|
+
});
|
|
4479
|
+
attempts.push({
|
|
4480
|
+
type: "indeterminate",
|
|
4481
|
+
error
|
|
4482
|
+
});
|
|
4483
|
+
continue;
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
if (resolution.type === "verified") return resolution;
|
|
4487
|
+
const reason = resolution.type === "rejected" ? resolution.reason : "The document is not a portable actor.";
|
|
4488
|
+
logger.debug("The actor document served from {url} does not vouch for key {keyId}: {reason}", {
|
|
4489
|
+
keyId: formattedKeyId,
|
|
4490
|
+
url,
|
|
4491
|
+
reason
|
|
4492
|
+
});
|
|
4493
|
+
attempts.push({
|
|
4494
|
+
type: "rejected",
|
|
4495
|
+
reason
|
|
4496
|
+
});
|
|
4497
|
+
}
|
|
4498
|
+
const rejections = attempts.flatMap((a) => a.type === "rejected" ? [a.reason] : []);
|
|
4499
|
+
if (rejections.length === attempts.length) return reject(rejections.join(" "));
|
|
4500
|
+
const errors = attempts.flatMap((a) => a.type === "rejected" ? [] : [a.error]);
|
|
4501
|
+
const aggregate = errors.length === 1 ? errors[0] : new AggregateError(errors, `Failed to fetch the actor of key ${formattedKeyId} from any of its gateways: ${requestUrls.join(", ")}`);
|
|
4502
|
+
if (attempts.every((a) => a.type === "retrievalFailed")) {
|
|
4503
|
+
const statuses = errors.map((error) => error instanceof FetchError ? error.response?.status : void 0);
|
|
4504
|
+
return {
|
|
4505
|
+
type: "unavailable",
|
|
4506
|
+
error: statuses[0] != null && statuses.every((status) => status === statuses[0]) ? errors[0] : aggregate,
|
|
4507
|
+
cacheable: true
|
|
4508
|
+
};
|
|
4509
|
+
}
|
|
4510
|
+
return {
|
|
4511
|
+
type: "unavailable",
|
|
4512
|
+
error: new Error(`Could not determine whether the actor of key ${formattedKeyId} vouches for it.`, { cause: aggregate }),
|
|
4513
|
+
cacheable: false
|
|
4514
|
+
};
|
|
4515
|
+
}
|
|
4516
|
+
/**
|
|
4517
|
+
* Finds the nodes that stand for the key with the given canonical portable
|
|
4518
|
+
* ID. A node whose ID is an `ap:` or `ap+ef61:` URI stands for the key
|
|
4519
|
+
* itself, e.g., Mitra lists the keys of portable actors that way while
|
|
4520
|
+
* signing requests with compatible key IDs. A node whose ID is a compatible
|
|
4521
|
+
* identifier stands for a gateway's key, so it matches only a compatible key
|
|
4522
|
+
* ID on the same gateway; a key ID that names no gateway never selects
|
|
4523
|
+
* a gateway's key, even with the same fragment.
|
|
4524
|
+
* @param values The expanded values of a key property.
|
|
4525
|
+
* @param canonicalKeyId The canonical portable ID of the key ID.
|
|
4526
|
+
* @param gateway The origin of the gateway whose key the key ID names, or
|
|
4527
|
+
* `null` if the key ID names no gateway.
|
|
4528
|
+
*/
|
|
4529
|
+
function findNodes(values, canonicalKeyId, gateway) {
|
|
4198
4530
|
if (!Array.isArray(values)) return [];
|
|
4199
4531
|
const nodes = [];
|
|
4200
4532
|
for (const value of values) {
|
|
4201
4533
|
if (value == null || typeof value !== "object" || Array.isArray(value)) continue;
|
|
4202
4534
|
const node = value;
|
|
4203
4535
|
const nodeId = node["@id"];
|
|
4204
|
-
if (typeof nodeId !== "string"
|
|
4205
|
-
if (
|
|
4536
|
+
if (typeof nodeId !== "string") continue;
|
|
4537
|
+
if (getRawCanonicalPortableId(nodeId) !== canonicalKeyId) continue;
|
|
4538
|
+
const parsed = parseIri(nodeId);
|
|
4539
|
+
if (isPortableUri(parsed) || parsed.origin === gateway) nodes.push(node);
|
|
4206
4540
|
}
|
|
4207
4541
|
return nodes;
|
|
4208
4542
|
}
|
|
@@ -4580,13 +4914,18 @@ function keyFetchErrorResult(keyId, result) {
|
|
|
4580
4914
|
}
|
|
4581
4915
|
};
|
|
4582
4916
|
}
|
|
4917
|
+
/**
|
|
4918
|
+
* Creates the resolvers of keys of FEP-ef61 portable actors, which HTTP
|
|
4919
|
+
* Signature verification alone passes to key lookups.
|
|
4920
|
+
*/
|
|
4921
|
+
function createPortableKeyResolvers(options) {
|
|
4922
|
+
return {
|
|
4923
|
+
gatewayKey: (document, actor, keyId) => verifyPortableGatewayKeyDocument(document, actor, keyId, options),
|
|
4924
|
+
actorKey: (keyId) => resolvePortableActorKey(keyId, options)
|
|
4925
|
+
};
|
|
4926
|
+
}
|
|
4583
4927
|
function parseKeyId(value) {
|
|
4584
|
-
|
|
4585
|
-
try {
|
|
4586
|
-
return new URL(value);
|
|
4587
|
-
} catch {
|
|
4588
|
-
return null;
|
|
4589
|
-
}
|
|
4928
|
+
return value == null ? null : parseKeyIdString(value);
|
|
4590
4929
|
}
|
|
4591
4930
|
function getKeyFetchErrorName(error) {
|
|
4592
4931
|
return error.name || error.constructor.name || "Error";
|
|
@@ -4844,7 +5183,7 @@ async function verifyRequestDraft(request, span, metricsContext, { documentLoade
|
|
|
4844
5183
|
keyCache,
|
|
4845
5184
|
tracerProvider,
|
|
4846
5185
|
meterProvider,
|
|
4847
|
-
|
|
5186
|
+
portableKeyResolvers: createPortableKeyResolvers({
|
|
4848
5187
|
documentLoader,
|
|
4849
5188
|
contextLoader,
|
|
4850
5189
|
keyCache,
|
|
@@ -5064,7 +5403,7 @@ async function verifyRequestRfc9421(request, span, metricsContext, { documentLoa
|
|
|
5064
5403
|
keyCache,
|
|
5065
5404
|
tracerProvider,
|
|
5066
5405
|
meterProvider,
|
|
5067
|
-
|
|
5406
|
+
portableKeyResolvers: createPortableKeyResolvers({
|
|
5068
5407
|
documentLoader,
|
|
5069
5408
|
contextLoader,
|
|
5070
5409
|
keyCache,
|
|
@@ -5372,4 +5711,4 @@ function timingSafeEqual(a, b) {
|
|
|
5372
5711
|
return result === 0;
|
|
5373
5712
|
}
|
|
5374
5713
|
//#endregion
|
|
5375
|
-
export {
|
|
5714
|
+
export { recordCollectionRequest as $, isClearlyMalformedContextReference as A, fetchKeyDetailed as B, attachSignature as C, version as Ct, getNormalizationContextLoader as D, detachSignature as E, verifySignature as F, getDurationMs as G, importJwk as H, wrapContextLoaderForJsonLd as I, instrumentDocumentLoader as J, getFederationMetrics as K, exportJwk as L, signJsonLd as M, verifyCompactJsonLd as N, hasSignature as O, verifyJsonLd as P, recordCollectionPageItems as Q, fetchActorDocument as R, assertSafeJsonLd as S, name as St, createSignature as T, validateCryptoKey as U, generateCryptoKeyPair as V, verifyKeyOwnership as W, recordCircuitBreakerStateChange as X, isAbortError$1 as Y, recordCollectionDispatchDuration as Z, verifyPortableObjectProofPolicy as _, isCompatibleKeyId as _t, signRequest as a, recordOutboxEnqueue as at, normalizeOutgoingActivityJsonLd as b, isPortableUri as bt, fetchPortableGatewayKey as c, preloadedOnlyDocumentLoader as ct, createProof as d, parseAcceptSignature as dt, recordCollectionTotalItems as et, hasProofLike as f, validateAcceptSignature as ft, verifyPortableObjectProof as g, hasPortableActor as gt, verifyObject as h, getPortableDid as ht, selectRequestSignature as i, recordOutboxActivity as it, isInvalidUrlTypeError as j, hasSignatureLike as k, resolvePortableActorKey as l, formatAcceptSignature as lt, verifyMapLocalProof as m, getGatewayKeyBase as mt, listRequestSignatures as n, recordFanoutRecipients as nt, verifyRequest as o, recordWebFingerHandle as ot, signObject as p, getCanonicalPortableId as pt, getRemoteHost as q, parseRfc9421SignatureInput as r, recordInboxActivity as rt, verifyRequestDetailed as s, registerQueueDepthGauge as st, doubleKnock as t, recordDocumentCache as tt, InvalidPortableObjectIdError as u, fulfillAcceptSignature as ut, verifyPortableObjectProofWithRoot as v, isPortableId as vt, compactJsonLd as w, InvalidContextReferenceError as x, isSamePublicKey as xt, verifyProof as y, isPortableKeyId as yt, fetchKey as z };
|