@fedify/fedify 2.4.0-dev.1988 → 2.4.0-dev.1995

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.
Files changed (62) hide show
  1. package/dist/{builder-Cts78G9N.mjs → builder-D0DxgOV5.mjs} +2 -2
  2. package/dist/compat/transformers.test.mjs +1 -1
  3. package/dist/compound-proof-CJnWc6c-.mjs +495 -0
  4. package/dist/{deno-BgMEefEr.mjs → deno-CABhzCb_.mjs} +1 -1
  5. package/dist/{docloader-DEYs99FZ.mjs → docloader-BbGSL0Xq.mjs} +2 -2
  6. package/dist/federation/builder.test.mjs +1 -1
  7. package/dist/federation/handler-compound-proof.test.d.mts +2 -0
  8. package/dist/federation/handler-compound-proof.test.mjs +152 -0
  9. package/dist/federation/handler.test.mjs +5 -5
  10. package/dist/federation/idempotency.test.mjs +2 -2
  11. package/dist/federation/metrics.test.mjs +1 -1
  12. package/dist/federation/middleware.test.mjs +7 -7
  13. package/dist/federation/mod.cjs +1 -1
  14. package/dist/federation/mod.js +1 -1
  15. package/dist/federation/send.test.mjs +3 -3
  16. package/dist/federation/tasks/enqueue.test.mjs +1 -1
  17. package/dist/federation/tasks/tasks.test.mjs +2 -2
  18. package/dist/federation/temporal.test.mjs +1 -1
  19. package/dist/federation/webfinger.test.mjs +1 -1
  20. package/dist/{federation-DzPUG_AP.cjs → federation-DCEHQk4G.cjs} +542 -43
  21. package/dist/{http-CgwqtxAy.js → http-9WyuldYh.js} +2 -2
  22. package/dist/{http-Z3anvCd-.cjs → http-CRFns-UE.cjs} +2 -2
  23. package/dist/{http-CtidZS_t.mjs → http-D9urSO2D.mjs} +3 -3
  24. package/dist/{key-Cwbg5ggV.mjs → key-Ccs8cnd7.mjs} +2 -2
  25. package/dist/{kv-cache-BM2-w-Wq.cjs → kv-cache-DXT9vmIg.cjs} +1 -1
  26. package/dist/{kv-cache-CykuL0ya.js → kv-cache-DtmXhPXG.js} +1 -1
  27. package/dist/{kv-cache-DHiR8yTf.mjs → kv-cache-lKyFn_Dn.mjs} +1 -1
  28. package/dist/{ld-CzhdWyTt.mjs → ld-qup__MAW.mjs} +3 -3
  29. package/dist/map-local-context-conflict-DOYEEJ3u.mjs +204 -0
  30. package/dist/map-local-create-note-B0SeXJms.mjs +214 -0
  31. package/dist/{metrics-CrqsHP0l.mjs → metrics-CISXCvB1.mjs} +1 -1
  32. package/dist/{middleware-DCpiAsZi.mjs → middleware-CzvJvPHK.mjs} +52 -20
  33. package/dist/{middleware-CZpYxSKD.mjs → middleware-DkrU2WhY.mjs} +1 -1
  34. package/dist/{middleware-CeCj5caM.js → middleware-DsfWajaD.js} +511 -12
  35. package/dist/mod.cjs +19 -19
  36. package/dist/mod.js +4 -4
  37. package/dist/nodeinfo/handler.test.mjs +1 -1
  38. package/dist/{proof-CUghqhAf.js → owner-BIPEZGiU.js} +1239 -1139
  39. package/dist/{owner-BqVXJLW8.mjs → owner-CRoq8Spb.mjs} +2 -2
  40. package/dist/{proof-DHu5zI0Z.cjs → owner-CVA7L9MA.cjs} +1252 -1140
  41. package/dist/{proof-DL8Iid3a.mjs → proof-BDxNVZ3E.mjs} +176 -76
  42. package/dist/{send-6jS4xFsX.mjs → send-BzM5GLyn.mjs} +3 -3
  43. package/dist/sig/compound-proof-discovery.test.d.mts +2 -0
  44. package/dist/sig/compound-proof-discovery.test.mjs +331 -0
  45. package/dist/sig/compound-proof-verification.test.d.mts +2 -0
  46. package/dist/sig/compound-proof-verification.test.mjs +465 -0
  47. package/dist/sig/compound-proof.test.d.mts +2 -0
  48. package/dist/sig/compound-proof.test.mjs +324 -0
  49. package/dist/sig/http.test.mjs +2 -2
  50. package/dist/sig/key.test.mjs +1 -1
  51. package/dist/sig/ld.test.mjs +2 -2
  52. package/dist/sig/mod.cjs +17 -17
  53. package/dist/sig/mod.js +2 -2
  54. package/dist/sig/owner.test.mjs +1 -1
  55. package/dist/sig/proof.test.mjs +1 -1
  56. package/dist/{temporal-DcyzeytP.mjs → temporal-Dv6Qv-8k.mjs} +1 -1
  57. package/dist/testing/kv.test.mjs +1 -1
  58. package/dist/utils/docloader.test.mjs +2 -2
  59. package/dist/utils/kv-cache.test.mjs +1 -1
  60. package/dist/utils/mod.cjs +1 -1
  61. package/dist/utils/mod.js +1 -1
  62. package/package.json +6 -6
@@ -0,0 +1,324 @@
1
+ import { Temporal } from "temporal-polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { t as assertEquals } from "../assert_equals-CBlRfA-_.mjs";
5
+ import "../std__assert-CxFT0MNt.mjs";
6
+ import { t as assert } from "../assert-CebeUf0C.mjs";
7
+ import { n as ed25519PrivateKey, r as ed25519PublicKey } from "../keys-DIJNHW-Y.mjs";
8
+ import { n as preloadedOnlyDocumentLoader } from "../public-audience-Cc2YJ3ip.mjs";
9
+ import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-B5Ne7JoL.mjs";
10
+ import { c as verifyProof, r as signObject } from "../proof-BDxNVZ3E.mjs";
11
+ import { t as map_local_create_note_default } from "../map-local-create-note-B0SeXJms.mjs";
12
+ import { t as map_local_context_conflict_default } from "../map-local-context-conflict-DOYEEJ3u.mjs";
13
+ import { Create, DataIntegrityProof, Note } from "@fedify/vocab";
14
+ import { mockDocumentLoader, test } from "@fedify/fixture";
15
+ import { encodeMultibase, exportDidKey, parseIri } from "@fedify/vocab-runtime";
16
+ import { encodeHex } from "byte-encodings/hex";
17
+ import jsonld from "@fedify/vocab-runtime/jsonld";
18
+ import serialize from "json-canon";
19
+ //#region src/sig/compound-proof.test.ts
20
+ const outerPrivateKey = await crypto.subtle.importKey("jwk", {
21
+ kty: "OKP",
22
+ crv: "Ed25519",
23
+ d: "yW756hDF5BTEcXI6_53nLDX6W3D66X6IMuysfS4rjtY",
24
+ x: "sA2Nk45_dz1RVlqtNqYj9TRPf10ZYPnPPo4SYg6igQ8",
25
+ key_ops: ["sign"],
26
+ ext: true
27
+ }, "Ed25519", true, ["sign"]);
28
+ const outerDid = await exportDidKey(await crypto.subtle.importKey("jwk", {
29
+ kty: "OKP",
30
+ crv: "Ed25519",
31
+ x: "sA2Nk45_dz1RVlqtNqYj9TRPf10ZYPnPPo4SYg6igQ8",
32
+ key_ops: ["verify"],
33
+ ext: true
34
+ }, "Ed25519", true, ["verify"]));
35
+ const innerDid = await exportDidKey(ed25519PublicKey.publicKey);
36
+ const outerMethod = outerDid.substring(8);
37
+ const innerMethod = innerDid.substring(8);
38
+ const outerKeyId = new URL(`${outerDid}#${outerMethod}`);
39
+ const innerKeyId = new URL(`${innerDid}#${innerMethod}`);
40
+ const vectorInnerKeyId = new URL(map_local_create_note_default.keys.inner.verificationMethod);
41
+ const conflictVectorInnerKeyId = new URL(map_local_context_conflict_default.keys.inner.verificationMethod);
42
+ const context = ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/data-integrity/v1"];
43
+ const distinctInnerContext = [...context, { ex: "https://example.com/ns#" }];
44
+ const options = {
45
+ context,
46
+ contextLoader: mockDocumentLoader,
47
+ documentLoader: mockDocumentLoader
48
+ };
49
+ async function parseProof(document) {
50
+ const proof = document.proof;
51
+ assert(proof != null && typeof proof === "object" && !Array.isArray(proof));
52
+ return await DataIntegrityProof.fromJsonLd({
53
+ "@context": document["@context"],
54
+ ...proof
55
+ }, options);
56
+ }
57
+ function asRecord(value) {
58
+ assert(value != null && typeof value === "object" && !Array.isArray(value));
59
+ return value;
60
+ }
61
+ function withoutDirectProof(document) {
62
+ const unsecuredDocument = structuredClone(document);
63
+ delete unsecuredDocument.proof;
64
+ return unsecuredDocument;
65
+ }
66
+ function withoutProofValue(proof) {
67
+ const proofConfiguration = structuredClone(proof);
68
+ delete proofConfiguration.proofValue;
69
+ return proofConfiguration;
70
+ }
71
+ async function sha256(value) {
72
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value)));
73
+ }
74
+ async function assertRecordedProof(entry) {
75
+ assertEquals(withoutProofValue(entry.proof), entry.proofConfiguration);
76
+ assertEquals(entry.proof.proofValue, entry.proofValue);
77
+ const documentJcs = serialize(entry.document);
78
+ const proofConfigurationJcs = serialize(entry.proofConfiguration);
79
+ assertEquals(documentJcs, entry.canonicalization.documentJcs);
80
+ assertEquals(proofConfigurationJcs, entry.canonicalization.proofConfigurationJcs);
81
+ const documentDigest = await sha256(documentJcs);
82
+ const proofConfigurationDigest = await sha256(proofConfigurationJcs);
83
+ assertEquals(encodeHex(documentDigest), entry.hashes.documentSha256);
84
+ assertEquals(encodeHex(proofConfigurationDigest), entry.hashes.proofConfigurationSha256);
85
+ const combinedSigningInput = new Uint8Array(proofConfigurationDigest.length + documentDigest.length);
86
+ combinedSigningInput.set(proofConfigurationDigest);
87
+ combinedSigningInput.set(documentDigest, proofConfigurationDigest.length);
88
+ assertEquals(encodeHex(combinedSigningInput), entry.hashes.combinedSigningInput);
89
+ assertEquals(entry.hashes.combinedSigningInput, entry.hashes.proofConfigurationSha256 + entry.hashes.documentSha256);
90
+ const privateJwk = structuredClone(entry.key.testPrivateKeyJwk);
91
+ const publicJwk = structuredClone(entry.key.publicKeyJwk);
92
+ assertEquals(privateJwk.x, publicJwk.x);
93
+ const privateKey = await crypto.subtle.importKey("jwk", privateJwk, "Ed25519", true, ["sign"]);
94
+ const publicKey = await crypto.subtle.importKey("jwk", publicJwk, "Ed25519", true, ["verify"]);
95
+ const controller = await exportDidKey(publicKey);
96
+ assertEquals(controller, entry.key.controller);
97
+ const publicKeyMultibase = controller.replace(/^did:key:/, "");
98
+ assertEquals(publicKeyMultibase, entry.key.publicKeyMultibase);
99
+ assertEquals(entry.key.verificationMethod, `${controller}#${publicKeyMultibase}`);
100
+ assertEquals(entry.proofConfiguration.verificationMethod, entry.key.verificationMethod);
101
+ const signature = new Uint8Array(await crypto.subtle.sign("Ed25519", privateKey, combinedSigningInput));
102
+ assert(await crypto.subtle.verify("Ed25519", publicKey, signature, combinedSigningInput));
103
+ assertEquals(new TextDecoder().decode(encodeMultibase("base58btc", signature)), entry.proofValue);
104
+ }
105
+ test("map-local compound vector records independently reproducible proofs", async () => {
106
+ const securedOuter = asRecord(map_local_create_note_default.documents.finalSecuredCompound);
107
+ const securedInner = asRecord(map_local_create_note_default.documents.securedInner);
108
+ const outerProof = asRecord(securedOuter.proof);
109
+ const innerProof = asRecord(securedInner.proof);
110
+ const replacementInnerProof = asRecord(map_local_create_note_default.documents.replacementInnerProof);
111
+ const replacementInnerProofConfiguration = withoutProofValue(replacementInnerProof);
112
+ assertEquals(withoutDirectProof(securedOuter), map_local_create_note_default.documents.outerUnsecuredDocument);
113
+ assertEquals(withoutDirectProof(securedInner), map_local_create_note_default.documents.innerUnsecuredDocument);
114
+ assertEquals(withoutProofValue(outerProof), map_local_create_note_default.documents.outerProofConfiguration);
115
+ assertEquals(withoutProofValue(innerProof), map_local_create_note_default.documents.innerProofConfiguration);
116
+ const entries = [
117
+ {
118
+ document: map_local_create_note_default.documents.outerUnsecuredDocument,
119
+ proofConfiguration: map_local_create_note_default.documents.outerProofConfiguration,
120
+ proof: outerProof,
121
+ key: map_local_create_note_default.keys.outer,
122
+ canonicalization: map_local_create_note_default.canonicalization.outer,
123
+ hashes: map_local_create_note_default.hashes.outer,
124
+ proofValue: map_local_create_note_default.proofValues.outer
125
+ },
126
+ {
127
+ document: map_local_create_note_default.documents.innerUnsecuredDocument,
128
+ proofConfiguration: map_local_create_note_default.documents.innerProofConfiguration,
129
+ proof: innerProof,
130
+ key: map_local_create_note_default.keys.inner,
131
+ canonicalization: map_local_create_note_default.canonicalization.inner,
132
+ hashes: map_local_create_note_default.hashes.inner,
133
+ proofValue: map_local_create_note_default.proofValues.inner
134
+ },
135
+ {
136
+ document: map_local_create_note_default.documents.innerUnsecuredDocument,
137
+ proofConfiguration: replacementInnerProofConfiguration,
138
+ proof: replacementInnerProof,
139
+ key: map_local_create_note_default.keys.inner,
140
+ canonicalization: map_local_create_note_default.canonicalization.replacementInner,
141
+ hashes: map_local_create_note_default.hashes.replacementInner,
142
+ proofValue: map_local_create_note_default.proofValues.replacementInner
143
+ }
144
+ ];
145
+ for (const entry of entries) await assertRecordedProof(entry);
146
+ });
147
+ test("the context-conflict vector records valid proofs and divergent semantics", async () => {
148
+ const compound = asRecord(map_local_context_conflict_default.documents.finalSecuredCompound);
149
+ const embedded = asRecord(compound.object);
150
+ const securedInner = asRecord(map_local_context_conflict_default.documents.securedInner);
151
+ const outerProof = asRecord(compound.proof);
152
+ const innerProof = asRecord(embedded.proof);
153
+ assertEquals(embedded, securedInner);
154
+ assertEquals(withoutDirectProof(compound), map_local_context_conflict_default.documents.outerUnsecuredDocument);
155
+ assertEquals(withoutDirectProof(embedded), map_local_context_conflict_default.documents.innerUnsecuredDocument);
156
+ await assertRecordedProof({
157
+ document: map_local_context_conflict_default.documents.outerUnsecuredDocument,
158
+ proofConfiguration: map_local_context_conflict_default.documents.outerProofConfiguration,
159
+ proof: outerProof,
160
+ key: map_local_context_conflict_default.keys.outer,
161
+ canonicalization: map_local_context_conflict_default.canonicalization.outer,
162
+ hashes: map_local_context_conflict_default.hashes.outer,
163
+ proofValue: map_local_context_conflict_default.proofValues.outer
164
+ });
165
+ await assertRecordedProof({
166
+ document: map_local_context_conflict_default.documents.innerUnsecuredDocument,
167
+ proofConfiguration: map_local_context_conflict_default.documents.innerProofConfiguration,
168
+ proof: innerProof,
169
+ key: map_local_context_conflict_default.keys.inner,
170
+ canonicalization: map_local_context_conflict_default.canonicalization.inner,
171
+ hashes: map_local_context_conflict_default.hashes.inner,
172
+ proofValue: map_local_context_conflict_default.proofValues.inner
173
+ });
174
+ const inboundOptions = {
175
+ contextLoader: preloadedOnlyDocumentLoader,
176
+ documentLoader: preloadedOnlyDocumentLoader
177
+ };
178
+ const verifiedInner = await verifyProof(embedded, await parseProof(embedded), inboundOptions);
179
+ assertEquals(verifiedInner != null, map_local_context_conflict_default.expectedVerification.original.inner);
180
+ assertEquals(verifiedInner?.id, conflictVectorInnerKeyId);
181
+ const verifiedOuter = await verifyProof(compound, await parseProof(compound), inboundOptions);
182
+ assertEquals(verifiedOuter != null, map_local_context_conflict_default.expectedVerification.original.outer);
183
+ assertEquals(verifiedOuter?.id, outerKeyId);
184
+ const standaloneExpansion = await jsonld.expand(embedded, { documentLoader: preloadedOnlyDocumentLoader });
185
+ const compoundExpansion = await jsonld.expand(compound, { documentLoader: preloadedOnlyDocumentLoader });
186
+ const content = "https://www.w3.org/ns/activitystreams#content";
187
+ const object = "https://www.w3.org/ns/activitystreams#object";
188
+ const standaloneContent = asRecord(standaloneExpansion[0])[content];
189
+ const inParentObject = asRecord(asRecord(compoundExpansion[0])[object][0]);
190
+ const inParentContent = inParentObject[content];
191
+ assertEquals(serialize(standaloneExpansion[0]) === serialize(inParentObject), map_local_context_conflict_default.expectedInterpretation.standaloneAndInParentExpansionsEqual);
192
+ assertEquals(standaloneContent, [{ "@value": "A portable note with inherited language" }]);
193
+ assertEquals(inParentContent, [{
194
+ "@value": "A portable note with inherited language",
195
+ "@language": map_local_context_conflict_default.expectedInterpretation.inParentContentLanguage
196
+ }]);
197
+ assertEquals(standaloneContent[0]["@language"] ?? null, map_local_context_conflict_default.expectedInterpretation.standaloneContentLanguage);
198
+ assertEquals(serialize(standaloneContent) !== serialize(inParentContent), !map_local_context_conflict_default.expectedInterpretation.standaloneAndInParentExpansionsEqual);
199
+ });
200
+ test("the raw same-context baseline verifies map-locally", async () => {
201
+ const compound = structuredClone(map_local_create_note_default.documents.finalSecuredCompound);
202
+ const embedded = compound.object;
203
+ const embeddedProof = embedded.proof;
204
+ assertEquals(embedded, map_local_create_note_default.documents.securedInner);
205
+ assertEquals(embeddedProof["@context"], context);
206
+ assertEquals(embedded["@context"], context);
207
+ assert("proof" in embedded);
208
+ const verifiedInnerKey = await verifyProof(embedded, await parseProof(embedded), options);
209
+ assertEquals(verifiedInnerKey != null, map_local_create_note_default.expectedVerification.original.inner);
210
+ assertEquals(verifiedInnerKey != null, map_local_create_note_default.expectedVerification.standaloneInner);
211
+ assertEquals(verifiedInnerKey?.id, vectorInnerKeyId);
212
+ const verifiedOuterKey = await verifyProof(compound, await parseProof(compound), options);
213
+ assertEquals(verifiedOuterKey != null, map_local_create_note_default.expectedVerification.original.outer);
214
+ assertEquals(verifiedOuterKey != null, map_local_create_note_default.expectedVerification.standaloneOuter);
215
+ assertEquals(verifiedOuterKey?.id, outerKeyId);
216
+ const tampered = structuredClone(compound);
217
+ const tamperedInner = tampered.object;
218
+ tamperedInner.content = "A tampered portable note";
219
+ assertEquals(await verifyProof(tamperedInner, await parseProof(tamperedInner), options) != null, map_local_create_note_default.expectedVerification.tamperedInnerContent.inner);
220
+ assertEquals(await verifyProof(tampered, await parseProof(tampered), options) != null, map_local_create_note_default.expectedVerification.tamperedInnerContent.outer);
221
+ const replaced = structuredClone(compound);
222
+ const replacedInner = replaced.object;
223
+ replacedInner.proof = structuredClone(map_local_create_note_default.documents.replacementInnerProof);
224
+ const replacementInnerKey = await verifyProof(replacedInner, await parseProof(replacedInner), options);
225
+ assertEquals(replacementInnerKey != null, map_local_create_note_default.expectedVerification.replacedInnerProof.inner);
226
+ assertEquals(replacementInnerKey?.id, vectorInnerKeyId);
227
+ assertEquals(await verifyProof(replaced, await parseProof(replaced), options) != null, map_local_create_note_default.expectedVerification.replacedInnerProof.outer);
228
+ });
229
+ test("typed Create serialization bypasses a parsed child's JSON-LD cache", async () => {
230
+ const created = Temporal.Instant.from("2023-02-24T23:36:38Z");
231
+ const inner = await signObject(new Note({
232
+ id: parseIri(`ap+ef61://${innerDid}/objects/distinct-context`),
233
+ attribution: parseIri(`ap+ef61://${innerDid}/actor`),
234
+ content: "A portable note with its own context"
235
+ }), ed25519PrivateKey, innerKeyId, {
236
+ ...options,
237
+ context: distinctInnerContext,
238
+ created
239
+ });
240
+ const standaloneInner = await normalizeOutgoingActivityJsonLd(await inner.toJsonLd({
241
+ format: "compact",
242
+ ...options,
243
+ context: distinctInnerContext
244
+ }), mockDocumentLoader);
245
+ const compound = await normalizeOutgoingActivityJsonLd(await (await signObject(new Create({
246
+ id: parseIri(`ap+ef61://${outerDid}/activities/distinct-context`),
247
+ actor: parseIri(`ap+ef61://${outerDid}/actor`),
248
+ object: inner
249
+ }), outerPrivateKey, outerKeyId, {
250
+ ...options,
251
+ created
252
+ })).toJsonLd({
253
+ format: "compact",
254
+ ...options
255
+ }), mockDocumentLoader);
256
+ const embedded = compound.object;
257
+ const embeddedProof = embedded.proof;
258
+ const standaloneProof = await parseProof(standaloneInner);
259
+ assertEquals(standaloneInner["@context"], distinctInnerContext);
260
+ assertEquals(standaloneInner.proof["@context"], distinctInnerContext);
261
+ assertEquals(embedded["@context"], void 0);
262
+ assertEquals(embeddedProof["@context"], void 0);
263
+ assertEquals(embeddedProof.proofValue, standaloneInner.proof.proofValue);
264
+ const compactedStandalone = structuredClone(standaloneInner);
265
+ const compactedStandaloneProof = compactedStandalone.proof;
266
+ delete compactedStandalone["@context"];
267
+ delete compactedStandaloneProof["@context"];
268
+ assertEquals(embedded, compactedStandalone);
269
+ assertEquals((await verifyProof(standaloneInner, standaloneProof, options))?.id, innerKeyId);
270
+ const rewrittenContext = structuredClone(standaloneInner);
271
+ rewrittenContext["@context"] = context;
272
+ assertEquals(await verifyProof(rewrittenContext, standaloneProof, options), null);
273
+ assertEquals(await verifyProof(embedded, standaloneProof, options), null);
274
+ assertEquals((await verifyProof(compound, await parseProof(compound), options))?.id, outerKeyId);
275
+ const reparsedInner = await Note.fromJsonLd(standaloneInner, {
276
+ contextLoader: mockDocumentLoader,
277
+ documentLoader: mockDocumentLoader
278
+ });
279
+ assert(reparsedInner instanceof Note);
280
+ assertEquals(await reparsedInner.toJsonLd(), standaloneInner);
281
+ const reparsedCompound = await normalizeOutgoingActivityJsonLd(await (await signObject(new Create({
282
+ id: parseIri(`ap+ef61://${outerDid}/activities/reparsed-context`),
283
+ actor: parseIri(`ap+ef61://${outerDid}/actor`),
284
+ object: reparsedInner
285
+ }), outerPrivateKey, outerKeyId, {
286
+ ...options,
287
+ created
288
+ })).toJsonLd({
289
+ format: "compact",
290
+ ...options
291
+ }), mockDocumentLoader);
292
+ const reparsedEmbedded = reparsedCompound.object;
293
+ const reparsedEmbeddedProof = reparsedEmbedded.proof;
294
+ assertEquals(reparsedEmbedded["@context"], void 0);
295
+ assertEquals(reparsedEmbeddedProof["@context"], void 0);
296
+ assertEquals(reparsedEmbeddedProof.proofValue, standaloneInner.proof.proofValue);
297
+ assertEquals(reparsedEmbedded, compactedStandalone);
298
+ assertEquals(reparsedEmbedded, embedded);
299
+ assertEquals(await verifyProof(reparsedEmbedded, standaloneProof, options), null);
300
+ assertEquals((await verifyProof(reparsedCompound, await parseProof(reparsedCompound), options))?.id, outerKeyId);
301
+ });
302
+ test("verifyProof() does not invent a missing child context", async () => {
303
+ const received = structuredClone(map_local_create_note_default.documents.finalSecuredCompound);
304
+ const receivedInner = received.object;
305
+ const receivedInnerProof = receivedInner.proof;
306
+ delete receivedInner["@context"];
307
+ delete receivedInnerProof["@context"];
308
+ const inboundOptions = {
309
+ contextLoader: preloadedOnlyDocumentLoader,
310
+ documentLoader: preloadedOnlyDocumentLoader
311
+ };
312
+ const snapshot = structuredClone(received);
313
+ const proof = await DataIntegrityProof.fromJsonLd(received.proof, inboundOptions);
314
+ assertEquals(await verifyProof(received, proof, inboundOptions), null);
315
+ assertEquals(received, snapshot);
316
+ const guessed = structuredClone(received);
317
+ const guessedInner = guessed.object;
318
+ const guessedInnerProof = guessedInner.proof;
319
+ guessedInner["@context"] = structuredClone(guessed["@context"]);
320
+ guessedInnerProof["@context"] = structuredClone(guessed["@context"]);
321
+ assertEquals((await verifyProof(guessed, proof, inboundOptions))?.id, outerKeyId);
322
+ });
323
+ //#endregion
324
+ export {};
@@ -10,8 +10,8 @@ import { t as assertThrows } from "../assert_throws-BJ5wuvR2.mjs";
10
10
  import "../std__assert-CxFT0MNt.mjs";
11
11
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
12
12
  import { t as assert } from "../assert-CebeUf0C.mjs";
13
- import { t as exportJwk } from "../key-Cwbg5ggV.mjs";
14
- import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-CtidZS_t.mjs";
13
+ import { t as exportJwk } from "../key-Ccs8cnd7.mjs";
14
+ import { a as parseRfc9421Signature, c as timingSafeEqual, i as formatRfc9421SignatureParameters, l as verifyRequest, n as doubleKnock, o as parseRfc9421SignatureInput, r as formatRfc9421Signature, s as signRequest, t as createRfc9421SignatureBase, u as verifyRequestDetailed } from "../http-D9urSO2D.mjs";
15
15
  import { i as rsaPrivateKey2, l as rsaPublicKey5, o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
16
16
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
17
17
  import { FetchError, exportSpki } from "@fedify/vocab-runtime";
@@ -6,7 +6,7 @@ import { t as assertThrows } from "../assert_throws-BJ5wuvR2.mjs";
6
6
  import "../std__assert-CxFT0MNt.mjs";
7
7
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
8
8
  import { t as assert } from "../assert-CebeUf0C.mjs";
9
- import { a as generateCryptoKeyPair, i as fetchKeyDetailed, o as importJwk, r as fetchKey, s as validateCryptoKey, t as exportJwk } from "../key-Cwbg5ggV.mjs";
9
+ import { a as generateCryptoKeyPair, i as fetchKeyDetailed, o as importJwk, r as fetchKey, s as validateCryptoKey, t as exportJwk } from "../key-Ccs8cnd7.mjs";
10
10
  import { c as rsaPublicKey3, i as rsaPrivateKey2, o as rsaPublicKey1, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
11
11
  import { CryptographicKey, Multikey } from "@fedify/vocab";
12
12
  import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
@@ -8,9 +8,9 @@ import { t as assertInstanceOf } from "../assert_instance_of-g3WcyYNR.mjs";
8
8
  import { t as assertThrows } from "../assert_throws-BJ5wuvR2.mjs";
9
9
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
10
10
  import { t as assert } from "../assert-CebeUf0C.mjs";
11
- import { a as generateCryptoKeyPair } from "../key-Cwbg5ggV.mjs";
11
+ import { a as generateCryptoKeyPair } from "../key-Ccs8cnd7.mjs";
12
12
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
13
- import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-CzhdWyTt.mjs";
13
+ import { a as compactJsonLd, f as isInvalidUrlTypeError, g as verifySignature, h as verifyJsonLd, i as attachSignature, n as UnsafeJsonLdError, o as createSignature, p as signJsonLd, s as detachSignature, u as hasSignatureLike } from "../ld-qup__MAW.mjs";
14
14
  import { CryptographicKey } from "@fedify/vocab";
15
15
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { encodeBase64 } from "byte-encodings/base64";
package/dist/sig/mod.cjs CHANGED
@@ -1,31 +1,31 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_http = require("../http-Z3anvCd-.cjs");
4
- const require_proof = require("../proof-DHu5zI0Z.cjs");
5
- exports.attachSignature = require_proof.attachSignature;
6
- exports.createProof = require_proof.createProof;
7
- exports.createSignature = require_proof.createSignature;
8
- exports.detachSignature = require_proof.detachSignature;
9
- exports.doesActorOwnKey = require_proof.doesActorOwnKey;
3
+ const require_http = require("../http-CRFns-UE.cjs");
4
+ const require_owner = require("../owner-CVA7L9MA.cjs");
5
+ exports.attachSignature = require_owner.attachSignature;
6
+ exports.createProof = require_owner.createProof;
7
+ exports.createSignature = require_owner.createSignature;
8
+ exports.detachSignature = require_owner.detachSignature;
9
+ exports.doesActorOwnKey = require_owner.doesActorOwnKey;
10
10
  exports.exportJwk = require_http.exportJwk;
11
11
  exports.fetchKey = require_http.fetchKey;
12
12
  exports.fetchKeyDetailed = require_http.fetchKeyDetailed;
13
13
  exports.formatAcceptSignature = require_http.formatAcceptSignature;
14
14
  exports.fulfillAcceptSignature = require_http.fulfillAcceptSignature;
15
15
  exports.generateCryptoKeyPair = require_http.generateCryptoKeyPair;
16
- exports.getKeyOwner = require_proof.getKeyOwner;
17
- exports.hasProofLike = require_proof.hasProofLike;
18
- exports.hasSignatureLike = require_proof.hasSignatureLike;
16
+ exports.getKeyOwner = require_owner.getKeyOwner;
17
+ exports.hasProofLike = require_owner.hasProofLike;
18
+ exports.hasSignatureLike = require_owner.hasSignatureLike;
19
19
  exports.importJwk = require_http.importJwk;
20
20
  exports.parseAcceptSignature = require_http.parseAcceptSignature;
21
- exports.signJsonLd = require_proof.signJsonLd;
22
- exports.signObject = require_proof.signObject;
21
+ exports.signJsonLd = require_owner.signJsonLd;
22
+ exports.signObject = require_owner.signObject;
23
23
  exports.signRequest = require_http.signRequest;
24
24
  exports.validateAcceptSignature = require_http.validateAcceptSignature;
25
- exports.verifyJsonLd = require_proof.verifyJsonLd;
26
- exports.verifyObject = require_proof.verifyObject;
27
- exports.verifyPortableObjectProof = require_proof.verifyPortableObjectProof;
28
- exports.verifyProof = require_proof.verifyProof;
25
+ exports.verifyJsonLd = require_owner.verifyJsonLd;
26
+ exports.verifyObject = require_owner.verifyObject;
27
+ exports.verifyPortableObjectProof = require_owner.verifyPortableObjectProof;
28
+ exports.verifyProof = require_owner.verifyProof;
29
29
  exports.verifyRequest = require_http.verifyRequest;
30
30
  exports.verifyRequestDetailed = require_http.verifyRequestDetailed;
31
- exports.verifySignature = require_proof.verifySignature;
31
+ exports.verifySignature = require_owner.verifySignature;
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { F as validateAcceptSignature, M as formatAcceptSignature, N as fulfillAcceptSignature, P as parseAcceptSignature, a as verifyRequestDetailed, c as fetchKey, d as importJwk, i as verifyRequest, l as fetchKeyDetailed, o as exportJwk, r as signRequest, u as generateCryptoKeyPair } from "../http-CgwqtxAy.js";
4
- import { C as verifyJsonLd, a as verifyPortableObjectProof, c as doesActorOwnKey, f as attachSignature, h as detachSignature, i as verifyObject, l as getKeyOwner, m as createSignature, n as hasProofLike, o as verifyProof, r as signObject, t as createProof, v as hasSignatureLike, w as verifySignature, x as signJsonLd } from "../proof-CUghqhAf.js";
3
+ import { F as validateAcceptSignature, M as formatAcceptSignature, N as fulfillAcceptSignature, P as parseAcceptSignature, a as verifyRequestDetailed, c as fetchKey, d as importJwk, i as verifyRequest, l as fetchKeyDetailed, o as exportJwk, r as signRequest, u as generateCryptoKeyPair } from "../http-9WyuldYh.js";
4
+ import { S as signJsonLd, T as verifySignature, a as signObject, c as verifyPortableObjectProof, g as detachSignature, h as createSignature, i as hasProofLike, n as getKeyOwner, p as attachSignature, r as createProof, s as verifyObject, t as doesActorOwnKey, u as verifyProof, w as verifyJsonLd, y as hasSignatureLike } from "../owner-BIPEZGiU.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, hasProofLike, hasSignatureLike, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyPortableObjectProof, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import { t as assertFalse } from "../assert_false-3pLLLsO4.mjs";
6
6
  import "../std__assert-CxFT0MNt.mjs";
7
7
  import { t as assert } from "../assert-CebeUf0C.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-DIJNHW-Y.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-BqVXJLW8.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-CRoq8Spb.mjs";
10
10
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
11
11
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
12
12
  //#region src/sig/owner.test.ts
@@ -10,7 +10,7 @@ import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
10
10
  import { t as assert } from "../assert-CebeUf0C.mjs";
11
11
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-DIJNHW-Y.mjs";
12
12
  import { r as normalizeOutgoingActivityJsonLd } from "../outgoing-jsonld-B5Ne7JoL.mjs";
13
- import { a as verifyPortableObjectProof, i as verifyObject, n as hasProofLike, o as verifyProof, r as signObject, t as createProof } from "../proof-DL8Iid3a.mjs";
13
+ import { a as verifyObject, c as verifyProof, n as hasProofLike, o as verifyPortableObjectProof, r as signObject, t as createProof } from "../proof-BDxNVZ3E.mjs";
14
14
  import { Create, DataIntegrityProof, Document, Multikey, Note, PUBLIC_COLLECTION, Place, Translation } from "@fedify/vocab";
15
15
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
16
16
  import { decodeMultibase, encodeMultibase, exportDidKey, exportMultibaseKey, formatIri, importMultibaseKey, parseIri } from "@fedify/vocab-runtime";
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { c as getNormalizationContextLoader } from "./ld-CzhdWyTt.mjs";
4
+ import { c as getNormalizationContextLoader } from "./ld-qup__MAW.mjs";
5
5
  import jsonld from "@fedify/vocab-runtime/jsonld";
6
6
  //#region src/federation/temporal.ts
7
7
  function isPlainObject(value) {
@@ -6,7 +6,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
6
6
  import { t as ManualClockKvStore } from "../kv-DBRWVx3Q.mjs";
7
7
  import { n as baseOptions, o as stringSchema, t as MockQueue } from "../tasks-dbCShlCb.mjs";
8
8
  import { t as assertEquals } from "../assert_equals-CBlRfA-_.mjs";
9
- import { o as createFederation } from "../middleware-DCpiAsZi.mjs";
9
+ import { o as createFederation } from "../middleware-CzvJvPHK.mjs";
10
10
  //#region src/testing/kv.test.ts
11
11
  test("ManualClockKvStore keeps an entry at its exact expiration instant", async () => {
12
12
  const kv = new ManualClockKvStore();
@@ -5,9 +5,9 @@ import { t as esm_default } from "../esm-BHXXx4Wx.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-CBlRfA-_.mjs";
6
6
  import "../std__assert-CxFT0MNt.mjs";
7
7
  import { t as assertRejects } from "../assert_rejects-wFbSPn1O.mjs";
8
- import { l as verifyRequest } from "../http-CtidZS_t.mjs";
8
+ import { l as verifyRequest } from "../http-D9urSO2D.mjs";
9
9
  import { i as rsaPrivateKey2 } from "../keys-DIJNHW-Y.mjs";
10
- import { t as getAuthenticatedDocumentLoader } from "../docloader-DEYs99FZ.mjs";
10
+ import { t as getAuthenticatedDocumentLoader } from "../docloader-BbGSL0Xq.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { FetchError, UrlError } from "@fedify/vocab-runtime";
13
13
  //#region src/utils/docloader.test.ts
@@ -1,7 +1,7 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as kvCache, t as MockKvStore } from "../kv-cache-DHiR8yTf.mjs";
4
+ import { n as kvCache, t as MockKvStore } from "../kv-cache-lKyFn_Dn.mjs";
5
5
  import { deepStrictEqual, throws } from "node:assert";
6
6
  import { createTestMeterProvider, mockDocumentLoader, test } from "@fedify/fixture";
7
7
  import { preloadedContexts } from "@fedify/vocab-runtime";
@@ -1,5 +1,5 @@
1
1
  const { URLPattern } = require("urlpattern-polyfill");
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const require_kv_cache = require("../kv-cache-BM2-w-Wq.cjs");
3
+ const require_kv_cache = require("../kv-cache-DXT9vmIg.cjs");
4
4
  exports.getAuthenticatedDocumentLoader = require_kv_cache.getAuthenticatedDocumentLoader;
5
5
  exports.kvCache = require_kv_cache.kvCache;
package/dist/utils/mod.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import { Temporal } from "temporal-polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-CykuL0ya.js";
3
+ import { n as getAuthenticatedDocumentLoader, t as kvCache } from "../kv-cache-DtmXhPXG.js";
4
4
  export { getAuthenticatedDocumentLoader, kvCache };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/fedify",
3
- "version": "2.4.0-dev.1988+c5c9d617",
3
+ "version": "2.4.0-dev.1995+618fd4e7",
4
4
  "description": "An ActivityPub server framework",
5
5
  "keywords": [
6
6
  "ActivityPub",
@@ -151,10 +151,10 @@
151
151
  "structured-field-values": "^2.0.4",
152
152
  "temporal-polyfill": "^1.0.1",
153
153
  "urlpattern-polyfill": "^10.1.0",
154
- "@fedify/uri-template": "2.4.0-dev.1988+c5c9d617",
155
- "@fedify/vocab": "2.4.0-dev.1988+c5c9d617",
156
- "@fedify/vocab-runtime": "2.4.0-dev.1988+c5c9d617",
157
- "@fedify/webfinger": "2.4.0-dev.1988+c5c9d617"
154
+ "@fedify/vocab": "2.4.0-dev.1995+618fd4e7",
155
+ "@fedify/webfinger": "2.4.0-dev.1995+618fd4e7",
156
+ "@fedify/uri-template": "2.4.0-dev.1995+618fd4e7",
157
+ "@fedify/vocab-runtime": "2.4.0-dev.1995+618fd4e7"
158
158
  },
159
159
  "devDependencies": {
160
160
  "@std/assert": "npm:@jsr/std__assert@^0.226.0",
@@ -167,7 +167,7 @@
167
167
  "typescript": "^6.0.0",
168
168
  "wrangler": "^4.17.0",
169
169
  "@fedify/fixture": "2.0.0",
170
- "@fedify/vocab-tools": "^2.4.0-dev.1988+c5c9d617"
170
+ "@fedify/vocab-tools": "^2.4.0-dev.1995+618fd4e7"
171
171
  },
172
172
  "scripts": {
173
173
  "build:self": "tsdown",