@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
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import "temporal-polyfill";
|
|
2
|
-
import "urlpattern-polyfill";
|
|
3
|
-
globalThis.addEventListener = () => {};
|
|
4
|
-
import { l as isSamePublicKey, o as isPortableActorDocument, t as getCanonicalPortableId } from "./portable-key-id-T7lecIbt.mjs";
|
|
5
|
-
import { l as verifyPortableObjectProofWithRoot } from "./proof-CW8k0R1G.mjs";
|
|
6
|
-
import { getLogger } from "@logtape/logtape";
|
|
7
|
-
import { CryptographicKey, Multikey, Object as Object$1 } from "@fedify/vocab";
|
|
8
|
-
import { getDocumentLoader, isGatewayUrl } from "@fedify/vocab-runtime";
|
|
9
|
-
//#region src/sig/portable-key.ts
|
|
10
|
-
const logger = getLogger([
|
|
11
|
-
"fedify",
|
|
12
|
-
"sig",
|
|
13
|
-
"key"
|
|
14
|
-
]);
|
|
15
|
-
const SEC = "https://w3id.org/security#";
|
|
16
|
-
/**
|
|
17
|
-
* Verifies that the signed document of a portable actor vouches for
|
|
18
|
-
* the gateway key with the given ID.
|
|
19
|
-
*
|
|
20
|
-
* A gateway key is accepted only if:
|
|
21
|
-
*
|
|
22
|
-
* - the document is an actor whose portable ID, i.e., its `ap:` ID or
|
|
23
|
-
* the canonical portable ID of its compatible identifier, is the one
|
|
24
|
-
* the key ID is the compatible identifier of;
|
|
25
|
-
* - the document has a valid [FEP-8b32] Object Integrity Proof made by
|
|
26
|
-
* the DID of its ID, i.e., it satisfies the [FEP-ef61] proof policy;
|
|
27
|
-
* - the document embeds a `Multikey` with that ID in its `assertionMethod`,
|
|
28
|
-
* whose `controller` is the actor, as [FEP-521a] requires, and a key
|
|
29
|
-
* embedded in its `publicKey` with the same ID agrees with it; or, if
|
|
30
|
-
* no `assertionMethod` entry has that ID, the document embeds
|
|
31
|
-
* a `CryptographicKey` with that ID in its `publicKey`, whose `owner` is
|
|
32
|
-
* the actor, as some publishers, e.g., tootik, list their RSA keys only
|
|
33
|
-
* there;
|
|
34
|
-
* - no more than one entry of either property has that ID; and
|
|
35
|
-
* - the key ID's origin is one of the actor's `gateways`.
|
|
36
|
-
*
|
|
37
|
-
* [FEP-8b32]: https://w3id.org/fep/8b32
|
|
38
|
-
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
39
|
-
* [FEP-521a]: https://w3id.org/fep/521a
|
|
40
|
-
*
|
|
41
|
-
* @param document The raw JSON-LD document served at the key ID.
|
|
42
|
-
* @param actor The parsed document, which must be a portable actor.
|
|
43
|
-
* @param keyId The key ID, which must be a compatible key ID.
|
|
44
|
-
* @param options Loaders and telemetry providers.
|
|
45
|
-
* @returns The verification result, which is never `legacy`.
|
|
46
|
-
* @internal
|
|
47
|
-
*/
|
|
48
|
-
async function verifyPortableGatewayKeyDocument(document, actor, keyId, options = {}) {
|
|
49
|
-
const reject = (reason) => {
|
|
50
|
-
logger.debug("Failed to verify gateway key {keyId} of the portable actor {actorId}: {reason}", {
|
|
51
|
-
keyId: keyId.href,
|
|
52
|
-
actorId: actor.id?.href,
|
|
53
|
-
reason
|
|
54
|
-
});
|
|
55
|
-
return {
|
|
56
|
-
type: "rejected",
|
|
57
|
-
reason
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
const keyBase = new URL(keyId.href);
|
|
61
|
-
keyBase.hash = "";
|
|
62
|
-
const claimedActorId = getCanonicalPortableId(keyBase);
|
|
63
|
-
const actorId = actor.id == null ? null : getCanonicalPortableId(actor.id);
|
|
64
|
-
if (claimedActorId == null || actorId == null) return reject("The key ID or the actor ID is not a valid portable ID.");
|
|
65
|
-
if (claimedActorId !== actorId) return reject("The key ID is not a compatible identifier of the actor it dereferences to.");
|
|
66
|
-
let verification;
|
|
67
|
-
try {
|
|
68
|
-
verification = await verifyPortableObjectProofWithRoot(document, {
|
|
69
|
-
documentLoader: options.documentLoader,
|
|
70
|
-
contextLoader: options.contextLoader,
|
|
71
|
-
keyCache: options.keyCache,
|
|
72
|
-
tracerProvider: options.tracerProvider,
|
|
73
|
-
meterProvider: options.meterProvider
|
|
74
|
-
});
|
|
75
|
-
} catch (error) {
|
|
76
|
-
if (!(error instanceof TypeError)) throw error;
|
|
77
|
-
return reject(`The actor document is malformed: ${error.message}`);
|
|
78
|
-
}
|
|
79
|
-
const { result, root, expires } = verification;
|
|
80
|
-
if (!result.verified) return reject("The actor document does not satisfy the FEP-ef61 proof policy: " + result.reason.type);
|
|
81
|
-
if (root == null) return reject("The actor document could not be expanded.");
|
|
82
|
-
const refuse = (url) => Promise.reject(/* @__PURE__ */ new Error(`Refusing to fetch ${url}.`));
|
|
83
|
-
const parseEmbeddedPublicKey = async (node) => {
|
|
84
|
-
if (isReference(node)) return null;
|
|
85
|
-
let key;
|
|
86
|
-
try {
|
|
87
|
-
key = await CryptographicKey.fromJsonLd(node, {
|
|
88
|
-
documentLoader: refuse,
|
|
89
|
-
contextLoader: options.contextLoader,
|
|
90
|
-
tracerProvider: options.tracerProvider
|
|
91
|
-
});
|
|
92
|
-
} catch (error) {
|
|
93
|
-
if (!(error instanceof TypeError)) throw error;
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
return key.publicKey == null ? null : key;
|
|
97
|
-
};
|
|
98
|
-
let verifiedActor;
|
|
99
|
-
try {
|
|
100
|
-
verifiedActor = await Object$1.fromJsonLd(root, {
|
|
101
|
-
documentLoader: refuse,
|
|
102
|
-
contextLoader: options.contextLoader,
|
|
103
|
-
tracerProvider: options.tracerProvider
|
|
104
|
-
});
|
|
105
|
-
} catch (error) {
|
|
106
|
-
if (!(error instanceof TypeError)) throw error;
|
|
107
|
-
return reject("The verified actor document is malformed.");
|
|
108
|
-
}
|
|
109
|
-
if (!isPortableActorDocument(verifiedActor) || getCanonicalPortableId(verifiedActor.id) !== claimedActorId) return reject("The key ID is not a compatible identifier of the actor whose document is signed.");
|
|
110
|
-
actor = verifiedActor;
|
|
111
|
-
const assertionNodes = findNodes(root[`${SEC}assertionMethod`], keyId);
|
|
112
|
-
const publicKeyNodes = findNodes(root[`${SEC}publicKey`], keyId);
|
|
113
|
-
if (assertionNodes.length > 1 || publicKeyNodes.length > 1) return reject("The actor document has more than one key with the ID.");
|
|
114
|
-
let publicKey;
|
|
115
|
-
if (assertionNodes.length > 0) {
|
|
116
|
-
if (isReference(assertionNodes[0])) return reject("The actor document does not embed the key in its assertionMethod.");
|
|
117
|
-
let multikey;
|
|
118
|
-
try {
|
|
119
|
-
multikey = await Multikey.fromJsonLd(assertionNodes[0], {
|
|
120
|
-
documentLoader: refuse,
|
|
121
|
-
contextLoader: options.contextLoader,
|
|
122
|
-
tracerProvider: options.tracerProvider
|
|
123
|
-
});
|
|
124
|
-
} catch (error) {
|
|
125
|
-
if (!(error instanceof TypeError)) throw error;
|
|
126
|
-
return reject("The key in the assertionMethod is malformed.");
|
|
127
|
-
}
|
|
128
|
-
if (multikey.publicKey == null) return reject("The key in the assertionMethod has no public key.");
|
|
129
|
-
if (multikey.controllerId == null || getCanonicalPortableId(multikey.controllerId) !== actorId) return reject("The controller of the key is not the actor.");
|
|
130
|
-
publicKey = multikey.publicKey;
|
|
131
|
-
if (publicKeyNodes.length > 0 && !isReference(publicKeyNodes[0])) {
|
|
132
|
-
const embedded = await parseEmbeddedPublicKey(publicKeyNodes[0]);
|
|
133
|
-
if (embedded == null || !await isSamePublicKey(embedded.publicKey, publicKey) || embedded.ownerId != null && getCanonicalPortableId(embedded.ownerId) !== actorId) return reject("The key in the publicKey does not agree with the one in the assertionMethod.");
|
|
134
|
-
}
|
|
135
|
-
} else {
|
|
136
|
-
if (publicKeyNodes.length < 1) return reject("The actor document embeds the key in neither its assertionMethod nor its publicKey.");
|
|
137
|
-
const embedded = await parseEmbeddedPublicKey(publicKeyNodes[0]);
|
|
138
|
-
if (embedded == null) return reject("The key in the publicKey is not embedded or malformed.");
|
|
139
|
-
if (embedded.ownerId == null || getCanonicalPortableId(embedded.ownerId) !== actorId) return reject("The owner of the key is not the actor.");
|
|
140
|
-
publicKey = embedded.publicKey;
|
|
141
|
-
}
|
|
142
|
-
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.`);
|
|
143
|
-
const key = new CryptographicKey({
|
|
144
|
-
id: keyId,
|
|
145
|
-
owner: actor.id,
|
|
146
|
-
publicKey
|
|
147
|
-
});
|
|
148
|
-
return {
|
|
149
|
-
type: "verified",
|
|
150
|
-
actor,
|
|
151
|
-
key,
|
|
152
|
-
...expires == null ? {} : { expires }
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Fetches the document at a compatible key ID, and resolves the key as
|
|
157
|
-
* a gateway key if the document is a portable actor.
|
|
158
|
-
*
|
|
159
|
-
* @param keyId The key ID, which must be a compatible key ID.
|
|
160
|
-
* @param options Loaders and telemetry providers.
|
|
161
|
-
* @returns `legacy` if the document cannot be fetched or is not a portable
|
|
162
|
-
* actor, which leaves the key to the usual resolution; otherwise,
|
|
163
|
-
* the result of {@link verifyPortableGatewayKeyDocument}.
|
|
164
|
-
* @internal
|
|
165
|
-
*/
|
|
166
|
-
async function fetchPortableGatewayKey(keyId, options = {}) {
|
|
167
|
-
const documentLoader = options.documentLoader ?? getDocumentLoader();
|
|
168
|
-
const contextLoader = options.contextLoader ?? getDocumentLoader();
|
|
169
|
-
let remoteDocument;
|
|
170
|
-
try {
|
|
171
|
-
remoteDocument = await documentLoader(keyId.href);
|
|
172
|
-
} catch (error) {
|
|
173
|
-
logger.debug("Failed to fetch key {keyId}: {error}", {
|
|
174
|
-
keyId: keyId.href,
|
|
175
|
-
error
|
|
176
|
-
});
|
|
177
|
-
return { type: "legacy" };
|
|
178
|
-
}
|
|
179
|
-
let object;
|
|
180
|
-
try {
|
|
181
|
-
object = await Object$1.fromJsonLd(remoteDocument.document, {
|
|
182
|
-
documentLoader,
|
|
183
|
-
contextLoader,
|
|
184
|
-
tracerProvider: options.tracerProvider
|
|
185
|
-
});
|
|
186
|
-
} catch (error) {
|
|
187
|
-
if (!(error instanceof TypeError)) throw error;
|
|
188
|
-
return { type: "legacy" };
|
|
189
|
-
}
|
|
190
|
-
if (!isPortableActorDocument(object)) return { type: "legacy" };
|
|
191
|
-
return await verifyPortableGatewayKeyDocument(remoteDocument.document, object, keyId, {
|
|
192
|
-
...options,
|
|
193
|
-
documentLoader,
|
|
194
|
-
contextLoader
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
function findNodes(values, id) {
|
|
198
|
-
if (!Array.isArray(values)) return [];
|
|
199
|
-
const nodes = [];
|
|
200
|
-
for (const value of values) {
|
|
201
|
-
if (value == null || typeof value !== "object" || Array.isArray(value)) continue;
|
|
202
|
-
const node = value;
|
|
203
|
-
const nodeId = node["@id"];
|
|
204
|
-
if (typeof nodeId !== "string" || !URL.canParse(nodeId)) continue;
|
|
205
|
-
if (new URL(nodeId).href === id.href) nodes.push(node);
|
|
206
|
-
}
|
|
207
|
-
return nodes;
|
|
208
|
-
}
|
|
209
|
-
/** A node with nothing but an `@id` is a reference, not an embedded key. */
|
|
210
|
-
function isReference(node) {
|
|
211
|
-
return Object.keys(node).every((key) => key === "@id");
|
|
212
|
-
}
|
|
213
|
-
//#endregion
|
|
214
|
-
export { verifyPortableGatewayKeyDocument as n, fetchPortableGatewayKey as t };
|