@fedify/fedify 2.1.12 → 2.1.14

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 (96) hide show
  1. package/dist/{builder-D9hlyCx5.mjs → builder-BBifZZ5G.mjs} +3 -3
  2. package/dist/{chunk-nlSIicah.js → chunk-CRNNMoPX.js} +2 -2
  3. package/dist/{client-z-8dc-e1.d.cts → client-CAM_bQXx.d.cts} +1 -0
  4. package/dist/{client-AtlibPOU.d.ts → client-CSddvgWN.d.ts} +1 -2
  5. package/dist/compat/mod.d.cts +2 -1
  6. package/dist/compat/mod.d.ts +2 -3
  7. package/dist/compat/mod.js +3 -3
  8. package/dist/compat/transformers.test.mjs +1 -1
  9. package/dist/{context-C0fssarc.d.ts → context-_l9t359k.d.ts} +53 -12
  10. package/dist/{context-LmrZPwti.d.cts → context-o22vjzS2.d.cts} +53 -10
  11. package/dist/{deno-Ddb3P7G7.mjs → deno-bqnW1QlD.mjs} +1 -1
  12. package/dist/{docloader-CK8tewt1.mjs → docloader-D-Fu0kBF.mjs} +2 -2
  13. package/dist/federation/builder.test.mjs +1 -1
  14. package/dist/federation/handler.test.mjs +1361 -41
  15. package/dist/federation/idempotency.test.mjs +2 -2
  16. package/dist/federation/inbox.test.mjs +1 -1
  17. package/dist/federation/middleware.test.mjs +1588 -84
  18. package/dist/federation/mod.cjs +1 -1
  19. package/dist/federation/mod.d.cts +4 -3
  20. package/dist/federation/mod.d.ts +4 -5
  21. package/dist/federation/mod.js +2 -2
  22. package/dist/federation/retry.test.mjs +1 -1
  23. package/dist/federation/send.test.mjs +3 -3
  24. package/dist/federation/temporal.test.d.mts +2 -0
  25. package/dist/federation/temporal.test.mjs +71 -0
  26. package/dist/federation/webfinger.test.mjs +1 -1
  27. package/dist/{http-CrGuipxe.d.cts → http-BDZeS5om.d.ts} +2 -1
  28. package/dist/{http-aQzN9Ayi.d.ts → http-C87EWkO0.d.cts} +2 -3
  29. package/dist/{http-CmDErAnD.cjs → http-CEXtUHix.cjs} +57 -9
  30. package/dist/{http-qKyJKSnF.js → http-Cw1EorUA.js} +58 -10
  31. package/dist/{http-DRDpStn2.mjs → http-DvhFwy2E.mjs} +58 -10
  32. package/dist/{inbox-DTuPJEma.mjs → inbox-7b3VYnec.mjs} +7 -4
  33. package/dist/{key-WSedbAA-.mjs → key-B3OBz6A_.mjs} +1 -1
  34. package/dist/{kv-CbLNp3zQ.d.cts → kv-D6hNiMTK.d.ts} +1 -0
  35. package/dist/{kv-cache-9cdQDeT0.cjs → kv-cache-BIapFiSV.cjs} +2 -2
  36. package/dist/{kv-cache-DNNRFY8u.js → kv-cache-C6nynGhh.js} +2 -2
  37. package/dist/{kv-cache-B01V7s3h.mjs → kv-cache-FsT1ljhs.mjs} +1 -1
  38. package/dist/{kv-GFYnFoOl.d.ts → kv-gJ8LYbxX.d.cts} +1 -3
  39. package/dist/ld-DTxYKZTT.mjs +550 -0
  40. package/dist/{middleware-UThUK30x.js → middleware-0vceVN10.js} +407 -82
  41. package/dist/{middleware-DFcgN1cH.cjs → middleware-BcbU5lKS.cjs} +406 -80
  42. package/dist/{middleware-8P6Z15Wq.cjs → middleware-DUT--Qen.cjs} +1 -1
  43. package/dist/{middleware-DDsnRvFC.mjs → middleware-DmT9t0BJ.mjs} +317 -84
  44. package/dist/{middleware-C2c1rlmE.mjs → middleware-Li_g_vqz.mjs} +1 -1
  45. package/dist/{mod-CnwZoDzx.d.ts → mod-0dF0OeGw.d.cts} +2 -3
  46. package/dist/{mod-B505FZBC.d.cts → mod-BTWFtZwa.d.ts} +4 -3
  47. package/dist/{mod-Cgpc49fA.d.cts → mod-Bv1elC-b.d.ts} +2 -1
  48. package/dist/{mod-DoJBjjnO.d.cts → mod-CjiK2zrW.d.ts} +3 -2
  49. package/dist/{mod-DvxszxXC.d.ts → mod-D5YlzzP3.d.cts} +3 -4
  50. package/dist/{mod-D7PAuO6k.d.ts → mod-dxOnKp2Y.d.cts} +4 -5
  51. package/dist/mod.cjs +4 -4
  52. package/dist/mod.d.cts +9 -8
  53. package/dist/mod.d.ts +9 -10
  54. package/dist/mod.js +9 -9
  55. package/dist/nodeinfo/handler.test.mjs +1 -1
  56. package/dist/nodeinfo/mod.d.cts +2 -1
  57. package/dist/nodeinfo/mod.d.ts +2 -3
  58. package/dist/nodeinfo/mod.js +3 -3
  59. package/dist/otel/mod.d.cts +2 -1
  60. package/dist/otel/mod.d.ts +2 -3
  61. package/dist/otel/mod.js +2 -2
  62. package/dist/{owner-CptqhsOy.d.cts → owner-CnngXDNJ.d.ts} +2 -1
  63. package/dist/{owner-74ARJ5TL.d.ts → owner-DEvZuyOE.d.cts} +2 -3
  64. package/dist/{owner-BceqCVOs.mjs → owner-DzcnuWYo.mjs} +2 -2
  65. package/dist/{proof-4NUQlbQV.js → proof-CtTT8A7y.js} +299 -5
  66. package/dist/{proof-BojC8L94.mjs → proof-DmVGi7mI.mjs} +2 -2
  67. package/dist/{proof-kuTIVfyZ.cjs → proof-JEoW3ODq.cjs} +345 -3
  68. package/dist/runtime/mod.d.cts +1 -0
  69. package/dist/runtime/mod.d.ts +1 -2
  70. package/dist/runtime/mod.js +3 -3
  71. package/dist/{send-Buz5Gy8x.mjs → send-5ulOKVCW.mjs} +2 -2
  72. package/dist/sig/http.test.mjs +120 -2
  73. package/dist/sig/key.test.mjs +1 -1
  74. package/dist/sig/ld.test.mjs +558 -2
  75. package/dist/sig/mod.cjs +2 -2
  76. package/dist/sig/mod.d.cts +4 -3
  77. package/dist/sig/mod.d.ts +4 -5
  78. package/dist/sig/mod.js +4 -4
  79. package/dist/sig/owner.test.mjs +1 -1
  80. package/dist/sig/proof.test.mjs +1 -1
  81. package/dist/temporal-CmJkd-25.mjs +95 -0
  82. package/dist/testing/mod.d.mts +48 -6
  83. package/dist/{transformers-ve6e2xcg.js → transformers-BGMIq1cs.js} +2 -2
  84. package/dist/{types-hvL8ElAs.js → types-CAY3OdLq.js} +2 -2
  85. package/dist/utils/docloader.test.mjs +2 -2
  86. package/dist/utils/kv-cache.test.mjs +1 -1
  87. package/dist/utils/mod.cjs +1 -1
  88. package/dist/utils/mod.d.cts +2 -1
  89. package/dist/utils/mod.d.ts +2 -3
  90. package/dist/utils/mod.js +3 -3
  91. package/dist/vocab/mod.d.cts +1 -0
  92. package/dist/vocab/mod.d.ts +1 -2
  93. package/dist/vocab/mod.js +2 -2
  94. package/package.json +7 -7
  95. package/dist/ld-OBpaLfHR.mjs +0 -256
  96. /package/dist/{retry-B_E3V_Dx.mjs → retry-CJL0poaU.mjs} +0 -0
@@ -5,13 +5,21 @@ import { t as assertEquals } from "../assert_equals-Ew3jOFa3.mjs";
5
5
  import { n as assertFalse, t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
6
6
  import { t as assertThrows } from "../assert_throws-4NwKEy2q.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
- import { i as generateCryptoKeyPair } from "../key-WSedbAA-.mjs";
8
+ import { i as generateCryptoKeyPair } from "../key-B3OBz6A_.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
10
- import { a as signJsonLd, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-OBpaLfHR.mjs";
10
+ import { a as compactJsonLd, d as isInvalidUrlTypeError, f as signJsonLd, h as verifySignature, i as attachSignature, m as verifyJsonLd, n as UnsafeJsonLdError, o as createSignature, s as detachSignature } from "../ld-DTxYKZTT.mjs";
11
11
  import { mockDocumentLoader, test } from "@fedify/fixture";
12
12
  import { CryptographicKey } from "@fedify/vocab";
13
13
  import { encodeBase64 } from "byte-encodings/base64";
14
14
  //#region src/sig/ld.test.ts
15
+ test("isInvalidUrlTypeError()", () => {
16
+ assert(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("Invalid URL: http://[")));
17
+ assert(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("\"http://[\" cannot be parsed as a URL.")));
18
+ const error = /* @__PURE__ */ new TypeError("Failed to parse URL");
19
+ error.code = "ERR_INVALID_URL";
20
+ assert(isInvalidUrlTypeError(error));
21
+ assertFalse(isInvalidUrlTypeError(/* @__PURE__ */ new TypeError("Failed to fetch")));
22
+ });
15
23
  test("attachSignature()", () => {
16
24
  const sig = {
17
25
  "@context": "https://w3id.org/identity/v1",
@@ -207,5 +215,553 @@ test("verifyJsonLd()", async () => {
207
215
  contextLoader: mockDocumentLoader
208
216
  }));
209
217
  });
218
+ test("compactJsonLd() with restrictive context loader", async () => {
219
+ const restrictiveContextLoader = async (resource) => {
220
+ const url = new URL(resource).href;
221
+ if (url === "https://www.w3.org/ns/activitystreams" || url === "https://w3id.org/identity/v1") return await mockDocumentLoader(url);
222
+ throw new Error(`Unexpected context: ${url}`);
223
+ };
224
+ const signed = await signJsonLd({
225
+ "@context": [
226
+ "https://www.w3.org/ns/activitystreams",
227
+ "https://w3id.org/identity/v1",
228
+ "https://w3id.org/security/v1",
229
+ "https://w3id.org/security/data-integrity/v1"
230
+ ],
231
+ id: "https://example.com/1",
232
+ type: "Create",
233
+ actor: "https://example.com/person2"
234
+ }, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
235
+ assertEquals(await compactJsonLd(signed, restrictiveContextLoader), {
236
+ "@context": [
237
+ "https://w3id.org/identity/v1",
238
+ "https://www.w3.org/ns/activitystreams",
239
+ "https://w3id.org/security/v1",
240
+ "https://w3id.org/security/data-integrity/v1"
241
+ ],
242
+ id: "https://example.com/1",
243
+ type: "Create",
244
+ actor: "https://example.com/person2",
245
+ signature: signed.signature
246
+ });
247
+ });
248
+ test("compactJsonLd() caches repeated remote contexts across graph scan and compaction", async () => {
249
+ const remoteUrl = "https://example.com/context";
250
+ let calls = 0;
251
+ const countingLoader = async (resource) => {
252
+ const url = new URL(resource).href;
253
+ if (url === remoteUrl) {
254
+ calls++;
255
+ return {
256
+ contextUrl: null,
257
+ documentUrl: url,
258
+ document: { "@context": { extra: "https://example.com/extra" } }
259
+ };
260
+ }
261
+ return await mockDocumentLoader(url);
262
+ };
263
+ await compactJsonLd({
264
+ "@context": "https://www.w3.org/ns/activitystreams",
265
+ id: "https://example.com/activities/remote-contexts",
266
+ type: "Create",
267
+ actor: "https://example.com/person2",
268
+ object: [
269
+ {
270
+ "@context": ["https://www.w3.org/ns/activitystreams", remoteUrl],
271
+ type: "Note",
272
+ content: "one"
273
+ },
274
+ {
275
+ "@context": ["https://www.w3.org/ns/activitystreams", remoteUrl],
276
+ type: "Note",
277
+ content: "two"
278
+ },
279
+ {
280
+ "@context": ["https://www.w3.org/ns/activitystreams", remoteUrl],
281
+ type: "Note",
282
+ content: "three"
283
+ }
284
+ ]
285
+ }, countingLoader);
286
+ assertEquals(calls, 1);
287
+ });
288
+ test("compactJsonLd() reuses the same remote context response for graph scan and compaction", async () => {
289
+ const remoteUrl = "https://example.com/context";
290
+ let calls = 0;
291
+ const compacted = await compactJsonLd({
292
+ "@context": [remoteUrl, "https://www.w3.org/ns/activitystreams"],
293
+ id: "https://example.com/activities/memoized-remote-context",
294
+ type: "Create",
295
+ actor: "https://example.com/person2",
296
+ graph: "https://example.com/custom-graph",
297
+ object: "https://example.com/notes/1"
298
+ }, async (resource) => {
299
+ const url = new URL(resource).href;
300
+ if (url === remoteUrl) {
301
+ calls++;
302
+ if (calls > 1) throw new Error(`Remote context should not be fetched twice: ${url}`);
303
+ return {
304
+ contextUrl: null,
305
+ documentUrl: url,
306
+ document: { "@context": { graph: "https://example.com/graph" } }
307
+ };
308
+ }
309
+ return await mockDocumentLoader(url);
310
+ });
311
+ assertEquals(calls, 1);
312
+ assertEquals(compacted, {
313
+ "@context": [
314
+ "https://w3id.org/identity/v1",
315
+ "https://www.w3.org/ns/activitystreams",
316
+ "https://w3id.org/security/v1",
317
+ "https://w3id.org/security/data-integrity/v1"
318
+ ],
319
+ id: "https://example.com/activities/memoized-remote-context",
320
+ type: "Create",
321
+ actor: "https://example.com/person2",
322
+ "https://example.com/graph": "https://example.com/custom-graph",
323
+ object: "https://example.com/notes/1"
324
+ });
325
+ });
326
+ test("compactJsonLd() preserves opaque top-level ids and resolves relative remote contexts against documentUrl during graph scan", async () => {
327
+ const rootContextId = "opaque-root";
328
+ const rootContextUrl = "https://example.com/contexts/root";
329
+ const childContextUrl = "https://example.com/contexts/child";
330
+ const calls = [];
331
+ const customLoader = async (resource) => {
332
+ calls.push(resource);
333
+ if (resource === rootContextId) return {
334
+ contextUrl: null,
335
+ documentUrl: rootContextUrl,
336
+ document: { "@context": {
337
+ "@import": "./child",
338
+ ext: "https://example.com/ext"
339
+ } }
340
+ };
341
+ if (resource === childContextUrl || resource === "child") return {
342
+ contextUrl: null,
343
+ documentUrl: childContextUrl,
344
+ document: { "@context": { child: "https://example.com/child" } }
345
+ };
346
+ return await mockDocumentLoader(resource);
347
+ };
348
+ assertEquals(await compactJsonLd({
349
+ "@context": [rootContextId, "https://www.w3.org/ns/activitystreams"],
350
+ id: "https://example.com/activities/custom-loader-contexts",
351
+ type: "Create",
352
+ actor: "https://example.com/person2",
353
+ ext: "preserve-me",
354
+ object: {
355
+ type: "Note",
356
+ content: "Hello"
357
+ }
358
+ }, customLoader), {
359
+ "@context": [
360
+ "https://w3id.org/identity/v1",
361
+ "https://www.w3.org/ns/activitystreams",
362
+ "https://w3id.org/security/v1",
363
+ "https://w3id.org/security/data-integrity/v1"
364
+ ],
365
+ id: "https://example.com/activities/custom-loader-contexts",
366
+ type: "Create",
367
+ actor: "https://example.com/person2",
368
+ "https://example.com/ext": "preserve-me",
369
+ object: {
370
+ type: "Note",
371
+ content: "Hello"
372
+ }
373
+ });
374
+ assert(calls.includes(rootContextId));
375
+ assert(calls.includes(childContextUrl));
376
+ assertFalse(calls.includes("./child"));
377
+ });
378
+ test("compactJsonLd() preserves base URLs for property-scoped remote contexts", async () => {
379
+ const rootContextId = "opaque-root";
380
+ const rootContextUrl = "https://example.com/contexts/root";
381
+ const childContextUrl = "https://example.com/contexts/child";
382
+ const calls = [];
383
+ const customLoader = async (resource) => {
384
+ calls.push(resource);
385
+ if (resource === rootContextId) return {
386
+ contextUrl: null,
387
+ documentUrl: rootContextUrl,
388
+ document: { "@context": { p: {
389
+ "@id": "https://example.com/p",
390
+ "@context": "./child"
391
+ } } }
392
+ };
393
+ if (resource === childContextUrl) return {
394
+ contextUrl: null,
395
+ documentUrl: childContextUrl,
396
+ document: { "@context": { nested: "https://example.com/nested" } }
397
+ };
398
+ return await mockDocumentLoader(resource);
399
+ };
400
+ assertEquals(await compactJsonLd({
401
+ "@context": [rootContextId, "https://www.w3.org/ns/activitystreams"],
402
+ id: "https://example.com/activities/property-scoped-contexts",
403
+ type: "Create",
404
+ actor: "https://example.com/person2",
405
+ p: { nested: "value" },
406
+ object: "https://example.com/notes/1"
407
+ }, customLoader), {
408
+ "@context": [
409
+ "https://w3id.org/identity/v1",
410
+ "https://www.w3.org/ns/activitystreams",
411
+ "https://w3id.org/security/v1",
412
+ "https://w3id.org/security/data-integrity/v1"
413
+ ],
414
+ id: "https://example.com/activities/property-scoped-contexts",
415
+ type: "Create",
416
+ actor: "https://example.com/person2",
417
+ "https://example.com/p": { "https://example.com/nested": "value" },
418
+ object: "https://example.com/notes/1"
419
+ });
420
+ assert(calls.includes(rootContextId));
421
+ assert(calls.includes(childContextUrl));
422
+ assertFalse(calls.includes("./child"));
423
+ });
424
+ test("compactJsonLd() ignores unsafe-looking keys inside @json values", async () => {
425
+ const remoteContextUrl = "https://example.com/contexts/json";
426
+ assertEquals(await compactJsonLd({
427
+ "@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
428
+ id: "https://example.com/activities/json-blob",
429
+ type: "Create",
430
+ actor: "https://example.com/person2",
431
+ blob: {
432
+ graph: { nested: true },
433
+ "@reverse": { nope: true },
434
+ "@included": [{ still: "raw-json" }]
435
+ },
436
+ object: "https://example.com/notes/1"
437
+ }, async (resource) => {
438
+ const url = new URL(resource).href;
439
+ if (url === remoteContextUrl) return {
440
+ contextUrl: null,
441
+ documentUrl: url,
442
+ document: { "@context": {
443
+ blob: {
444
+ "@id": "https://example.com/blob",
445
+ "@type": "@json"
446
+ },
447
+ graph: "@graph"
448
+ } }
449
+ };
450
+ return await mockDocumentLoader(url);
451
+ }), {
452
+ "@context": [
453
+ "https://w3id.org/identity/v1",
454
+ "https://www.w3.org/ns/activitystreams",
455
+ "https://w3id.org/security/v1",
456
+ "https://w3id.org/security/data-integrity/v1"
457
+ ],
458
+ id: "https://example.com/activities/json-blob",
459
+ type: "Create",
460
+ "https://example.com/blob": {
461
+ type: "@json",
462
+ "@value": {
463
+ graph: { nested: true },
464
+ "@reverse": { nope: true },
465
+ "@included": [{ still: "raw-json" }]
466
+ }
467
+ },
468
+ actor: "https://example.com/person2",
469
+ object: "https://example.com/notes/1"
470
+ });
471
+ });
472
+ test("compactJsonLd() ignores unsafe-looking keys inside inline @json value wrappers", async () => {
473
+ const remoteContextUrl = "https://example.com/contexts/inline-json";
474
+ assertEquals(await compactJsonLd({
475
+ "@context": [remoteContextUrl, "https://www.w3.org/ns/activitystreams"],
476
+ id: "https://example.com/activities/inline-json-blob",
477
+ type: "Create",
478
+ actor: "https://example.com/person2",
479
+ blob: {
480
+ "@value": {
481
+ graph: { nested: true },
482
+ "@reverse": { nope: true },
483
+ "@included": [{ still: "raw-json" }]
484
+ },
485
+ "@type": "@json"
486
+ },
487
+ object: "https://example.com/notes/1"
488
+ }, async (resource) => {
489
+ const url = new URL(resource).href;
490
+ if (url === remoteContextUrl) return {
491
+ contextUrl: null,
492
+ documentUrl: url,
493
+ document: { "@context": {
494
+ blob: "https://example.com/blob",
495
+ graph: "@graph"
496
+ } }
497
+ };
498
+ return await mockDocumentLoader(url);
499
+ }), {
500
+ "@context": [
501
+ "https://w3id.org/identity/v1",
502
+ "https://www.w3.org/ns/activitystreams",
503
+ "https://w3id.org/security/v1",
504
+ "https://w3id.org/security/data-integrity/v1"
505
+ ],
506
+ id: "https://example.com/activities/inline-json-blob",
507
+ type: "Create",
508
+ "https://example.com/blob": {
509
+ type: "@json",
510
+ "@value": {
511
+ graph: { nested: true },
512
+ "@reverse": { nope: true },
513
+ "@included": [{ still: "raw-json" }]
514
+ }
515
+ },
516
+ actor: "https://example.com/person2",
517
+ object: "https://example.com/notes/1"
518
+ });
519
+ });
520
+ test("verifyJsonLd() respects @graph alias overrides", async () => {
521
+ assert(await verifyJsonLd(await signJsonLd({
522
+ "@context": [
523
+ "https://www.w3.org/ns/activitystreams",
524
+ { graph: "@graph" },
525
+ { graph: "https://example.com/graph" }
526
+ ],
527
+ id: "https://example.com/activities/1",
528
+ type: "Create",
529
+ actor: "https://example.com/person2",
530
+ object: "https://example.com/notes/1",
531
+ graph: "https://example.com/custom-graph"
532
+ }, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader }), {
533
+ documentLoader: mockDocumentLoader,
534
+ contextLoader: mockDocumentLoader
535
+ }));
536
+ });
537
+ test("compactJsonLd() respects nested @context scope for @graph aliases", async () => {
538
+ assertEquals(await compactJsonLd({
539
+ "@context": ["https://www.w3.org/ns/activitystreams", {
540
+ graph: "https://example.com/graph",
541
+ meta: {
542
+ "@id": "https://example.com/meta",
543
+ "@context": { graph: "@graph" }
544
+ }
545
+ }],
546
+ id: "https://example.com/activities/2",
547
+ type: "Create",
548
+ actor: "https://example.com/person2",
549
+ object: "https://example.com/notes/2",
550
+ graph: "https://example.com/custom-graph",
551
+ meta: { value: "ok" }
552
+ }, mockDocumentLoader), {
553
+ "@context": [
554
+ "https://w3id.org/identity/v1",
555
+ "https://www.w3.org/ns/activitystreams",
556
+ "https://w3id.org/security/v1",
557
+ "https://w3id.org/security/data-integrity/v1"
558
+ ],
559
+ id: "https://example.com/activities/2",
560
+ type: "Create",
561
+ "https://example.com/graph": "https://example.com/custom-graph",
562
+ actor: "https://example.com/person2",
563
+ object: "https://example.com/notes/2",
564
+ "https://example.com/meta": { value: "ok" }
565
+ });
566
+ });
567
+ test("compactJsonLd() resets inherited @graph aliases on @context: null", async () => {
568
+ assertEquals(await compactJsonLd({
569
+ "@context": ["https://www.w3.org/ns/activitystreams", { g: "@graph" }],
570
+ id: "https://example.com/activities/3",
571
+ type: "Create",
572
+ actor: "https://example.com/person2",
573
+ object: {
574
+ "@context": null,
575
+ g: "literal"
576
+ }
577
+ }, mockDocumentLoader), {
578
+ "@context": [
579
+ "https://w3id.org/identity/v1",
580
+ "https://www.w3.org/ns/activitystreams",
581
+ "https://w3id.org/security/v1",
582
+ "https://w3id.org/security/data-integrity/v1"
583
+ ],
584
+ id: "https://example.com/activities/3",
585
+ type: "Create",
586
+ actor: "https://example.com/person2",
587
+ object: {}
588
+ });
589
+ });
590
+ test("compactJsonLd() rejects same-object forward @graph alias chains", async () => {
591
+ await assertRejects(() => compactJsonLd({
592
+ "@context": ["https://www.w3.org/ns/activitystreams", {
593
+ a: "b",
594
+ b: "@graph"
595
+ }],
596
+ id: "https://example.com/activities/forward-graph-alias",
597
+ type: "Create",
598
+ actor: "https://example.com/person2",
599
+ a: [{
600
+ id: "https://example.com/notes/forward-graph-alias",
601
+ type: "Note",
602
+ content: "Hello"
603
+ }]
604
+ }, mockDocumentLoader), UnsafeJsonLdError, "Unsupported JSON-LD keyword: @graph.");
605
+ });
606
+ test("compactJsonLd() preserves captured @graph aliases across later overrides", async () => {
607
+ await assertRejects(() => compactJsonLd({
608
+ "@context": [
609
+ "https://www.w3.org/ns/activitystreams",
610
+ { b: "@graph" },
611
+ { a: "b" },
612
+ { b: "https://example.com/b" }
613
+ ],
614
+ id: "https://example.com/activities/captured-graph-alias",
615
+ type: "Create",
616
+ actor: "https://example.com/person2",
617
+ a: [{
618
+ id: "https://example.com/notes/captured-graph-alias",
619
+ type: "Note",
620
+ content: "Hello"
621
+ }]
622
+ }, mockDocumentLoader), UnsafeJsonLdError, "Unsupported JSON-LD keyword: @graph.");
623
+ });
624
+ test("compactJsonLd() does not retroactively apply later @graph aliases", async () => {
625
+ assertEquals(await compactJsonLd({
626
+ "@context": [
627
+ "https://www.w3.org/ns/activitystreams",
628
+ { a: "b" },
629
+ { b: "@graph" }
630
+ ],
631
+ id: "https://example.com/activities/non-retroactive-graph-alias",
632
+ type: "Create",
633
+ actor: "https://example.com/person2",
634
+ a: [{
635
+ id: "https://example.com/notes/non-retroactive-graph-alias",
636
+ type: "Note",
637
+ content: "Hello"
638
+ }]
639
+ }, mockDocumentLoader), {
640
+ "@context": [
641
+ "https://w3id.org/identity/v1",
642
+ "https://www.w3.org/ns/activitystreams",
643
+ "https://w3id.org/security/v1",
644
+ "https://w3id.org/security/data-integrity/v1"
645
+ ],
646
+ id: "https://example.com/activities/non-retroactive-graph-alias",
647
+ type: "Create",
648
+ b: {
649
+ id: "https://example.com/notes/non-retroactive-graph-alias",
650
+ type: "Note",
651
+ content: "Hello"
652
+ },
653
+ actor: "https://example.com/person2"
654
+ });
655
+ });
656
+ test("verifyJsonLd() rejects unsafe JSON-LD keywords", async () => {
657
+ const original = {
658
+ "@context": "https://www.w3.org/ns/activitystreams",
659
+ id: "https://example.com/activities/undo",
660
+ type: "Undo",
661
+ actor: "https://example.com/person2",
662
+ object: {
663
+ id: "https://example.com/activities/announce",
664
+ type: "Announce",
665
+ actor: "https://example.com/person2",
666
+ object: "https://example.com/status/1"
667
+ }
668
+ };
669
+ const signed = await signJsonLd(original, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
670
+ const options = {
671
+ documentLoader: mockDocumentLoader,
672
+ contextLoader: mockDocumentLoader
673
+ };
674
+ const cases = [
675
+ ["@reverse", {
676
+ "@context": ["https://www.w3.org/ns/activitystreams", { rev: "@reverse" }],
677
+ id: "https://example.com/activities/announce",
678
+ type: "Announce",
679
+ actor: "https://example.com/person2",
680
+ object: "https://example.com/status/1",
681
+ rev: { object: {
682
+ id: "https://example.com/activities/undo",
683
+ type: "Undo",
684
+ actor: "https://example.com/person2"
685
+ } },
686
+ signature: signed.signature
687
+ }],
688
+ ["@included", {
689
+ "@context": ["https://www.w3.org/ns/activitystreams", { inc: "@included" }],
690
+ id: "https://example.com/activities/announce",
691
+ type: "Announce",
692
+ actor: "https://example.com/person2",
693
+ object: "https://example.com/status/1",
694
+ inc: [{
695
+ id: "https://example.com/activities/undo",
696
+ type: "Undo",
697
+ actor: "https://example.com/person2",
698
+ object: "https://example.com/activities/announce"
699
+ }],
700
+ signature: signed.signature
701
+ }],
702
+ ["@graph", {
703
+ "@context": ["https://www.w3.org/ns/activitystreams", { graph: "@graph" }],
704
+ graph: [original],
705
+ signature: signed.signature
706
+ }],
707
+ ["@graph", {
708
+ "@context": ["https://www.w3.org/ns/activitystreams", { graph: "@graph" }],
709
+ id: "https://example.com/activities/announce",
710
+ type: "Announce",
711
+ actor: "https://example.com/person2",
712
+ object: "https://example.com/status/1",
713
+ graph: [{
714
+ id: "https://example.com/activities/undo",
715
+ type: "Undo",
716
+ actor: "https://example.com/person2",
717
+ object: "https://example.com/activities/announce"
718
+ }],
719
+ signature: signed.signature
720
+ }]
721
+ ];
722
+ for (const [keyword, jsonLd] of cases) await assertRejects(() => verifyJsonLd(jsonLd, options), UnsafeJsonLdError, `Unsupported JSON-LD keyword: ${keyword}.`);
723
+ });
724
+ test("compactJsonLd() rejects unsafe JSON-LD keywords inside signature objects", async () => {
725
+ const signed = await signJsonLd({
726
+ "@context": "https://www.w3.org/ns/activitystreams",
727
+ id: "https://example.com/activities/signed-signature-keywords",
728
+ type: "Create",
729
+ actor: "https://example.com/person2",
730
+ object: "https://example.com/notes/1"
731
+ }, rsaPrivateKey3, rsaPublicKey3.id, { contextLoader: mockDocumentLoader });
732
+ for (const [keyword, value] of [
733
+ ["@reverse", { object: {
734
+ id: "https://example.com/activities/reverse-inside-signature",
735
+ type: "Undo"
736
+ } }],
737
+ ["@included", [{
738
+ id: "https://example.com/activities/included-inside-signature",
739
+ type: "Undo"
740
+ }]],
741
+ ["@graph", [{
742
+ id: "https://example.com/activities/graph-inside-signature",
743
+ type: "Undo"
744
+ }]]
745
+ ]) await assertRejects(() => compactJsonLd({
746
+ ...signed,
747
+ signature: {
748
+ ...signed.signature,
749
+ [keyword]: value
750
+ }
751
+ }, mockDocumentLoader), UnsafeJsonLdError, `Unsupported JSON-LD keyword: ${keyword}.`);
752
+ });
753
+ test("compactJsonLd() rejects inputs that compact into @graph wrappers", async () => {
754
+ await assertRejects(() => compactJsonLd([{
755
+ "@context": "https://www.w3.org/ns/activitystreams",
756
+ id: "https://example.com/notes/graph-wrapper-1",
757
+ type: "Note",
758
+ content: "one"
759
+ }, {
760
+ "@context": "https://www.w3.org/ns/activitystreams",
761
+ id: "https://example.com/notes/graph-wrapper-2",
762
+ type: "Note",
763
+ content: "two"
764
+ }], mockDocumentLoader), UnsafeJsonLdError, "Unsupported JSON-LD keyword: @graph.");
765
+ });
210
766
  //#endregion
211
767
  export {};
package/dist/sig/mod.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  const { Temporal } = require("@js-temporal/polyfill");
2
2
  const { URLPattern } = require("urlpattern-polyfill");
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
- const require_http = require("../http-CmDErAnD.cjs");
5
- const require_proof = require("../proof-kuTIVfyZ.cjs");
4
+ const require_http = require("../http-CEXtUHix.cjs");
5
+ const require_proof = require("../proof-JEoW3ODq.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
@@ -1,4 +1,5 @@
1
- import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-CrGuipxe.cjs";
2
- import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-CptqhsOy.cjs";
3
- import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-DoJBjjnO.cjs";
1
+ /// <reference lib="esnext.temporal" />
2
+ import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-C87EWkO0.cjs";
3
+ import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-DEvZuyOE.cjs";
4
+ import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-D5YlzzP3.cjs";
4
5
  export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
package/dist/sig/mod.d.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { Temporal } from "@js-temporal/polyfill";
2
- import { URLPattern } from "urlpattern-polyfill";
3
- import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-aQzN9Ayi.js";
4
- import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-74ARJ5TL.js";
5
- import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-DvxszxXC.js";
1
+ /// <reference lib="esnext.temporal" />
2
+ import { C as exportJwk, D as importJwk, E as generateCryptoKeyPair, S as KeyCache, T as fetchKeyDetailed, _ as validateAcceptSignature, a as VerifyRequestDetailedResult, b as FetchKeyOptions, c as signRequest, d as AcceptSignatureMember, f as AcceptSignatureParameters, g as parseAcceptSignature, h as fulfillAcceptSignature, i as SignRequestOptions, l as verifyRequest, m as formatAcceptSignature, n as HttpMessageSignaturesSpecDeterminer, o as VerifyRequestFailureReason, p as FulfillAcceptSignatureResult, r as Rfc9421SignRequestOptions, s as VerifyRequestOptions, t as HttpMessageSignaturesSpec, u as verifyRequestDetailed, v as FetchKeyDetailedResult, w as fetchKey, x as FetchKeyResult, y as FetchKeyErrorResult } from "../http-BDZeS5om.js";
3
+ import { i as getKeyOwner, n as GetKeyOwnerOptions, r as doesActorOwnKey, t as DoesActorOwnKeyOptions } from "../owner-CnngXDNJ.js";
4
+ import { _ as verifyJsonLd, a as createProof, c as verifyProof, d as VerifyJsonLdOptions, f as VerifySignatureOptions, g as signJsonLd, h as detachSignature, i as VerifyProofOptions, l as CreateSignatureOptions, m as createSignature, n as SignObjectOptions, o as signObject, p as attachSignature, r as VerifyObjectOptions, s as verifyObject, t as CreateProofOptions, u as SignJsonLdOptions, v as verifySignature } from "../mod-CjiK2zrW.js";
6
5
  export { AcceptSignatureMember, AcceptSignatureParameters, CreateProofOptions, CreateSignatureOptions, DoesActorOwnKeyOptions, FetchKeyDetailedResult, FetchKeyErrorResult, FetchKeyOptions, FetchKeyResult, FulfillAcceptSignatureResult, GetKeyOwnerOptions, HttpMessageSignaturesSpec, HttpMessageSignaturesSpecDeterminer, KeyCache, Rfc9421SignRequestOptions, SignJsonLdOptions, SignObjectOptions, SignRequestOptions, VerifyJsonLdOptions, VerifyObjectOptions, VerifyProofOptions, VerifyRequestDetailedResult, VerifyRequestFailureReason, VerifyRequestOptions, VerifySignatureOptions, attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
- import "@js-temporal/polyfill";
2
- import "urlpattern-polyfill";
3
- import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-qKyJKSnF.js";
4
- import { a as doesActorOwnKey, c as createSignature, d as signJsonLd, f as verifyJsonLd, i as verifyProof, l as detachSignature, n as signObject, o as getKeyOwner, p as verifySignature, r as verifyObject, s as attachSignature, t as createProof } from "../proof-4NUQlbQV.js";
1
+ import { Temporal } from "@js-temporal/polyfill";
2
+ import { URLPattern } from "urlpattern-polyfill";
3
+ import { a as verifyRequestDetailed, c as fetchKeyDetailed, f as formatAcceptSignature, h as validateAcceptSignature, i as verifyRequest, l as generateCryptoKeyPair, m as parseAcceptSignature, o as exportJwk, p as fulfillAcceptSignature, r as signRequest, s as fetchKey, u as importJwk } from "../http-Cw1EorUA.js";
4
+ import { _ as signJsonLd, a as doesActorOwnKey, b as verifySignature, d as createSignature, f as detachSignature, i as verifyProof, l as attachSignature, n as signObject, o as getKeyOwner, r as verifyObject, t as createProof, y as verifyJsonLd } from "../proof-CtTT8A7y.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, fetchKeyDetailed, formatAcceptSignature, fulfillAcceptSignature, generateCryptoKeyPair, getKeyOwner, importJwk, parseAcceptSignature, signJsonLd, signObject, signRequest, validateAcceptSignature, verifyJsonLd, verifyObject, verifyProof, verifyRequest, verifyRequestDetailed, verifySignature };
@@ -6,7 +6,7 @@ import "../std__assert-Duiq_YC9.mjs";
6
6
  import { n as assertFalse } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assert } from "../assert-ddO5KLpe.mjs";
8
8
  import { o as rsaPublicKey1, s as rsaPublicKey2 } from "../keys-BAK-tUlf.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-BceqCVOs.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DzcnuWYo.mjs";
10
10
  import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, CryptographicKey, lookupObject } from "@fedify/vocab";
12
12
  //#region src/sig/owner.test.ts
@@ -6,7 +6,7 @@ import "../std__assert-Duiq_YC9.mjs";
6
6
  import { t as assertRejects } from "../assert_rejects-B-qJtC9Z.mjs";
7
7
  import { t as assertInstanceOf } from "../assert_instance_of-C4Ri6VuN.mjs";
8
8
  import { i as rsaPrivateKey2, n as ed25519PrivateKey, r as ed25519PublicKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-BAK-tUlf.mjs";
9
- import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-BojC8L94.mjs";
9
+ import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-DmVGi7mI.mjs";
10
10
  import { mockDocumentLoader, test } from "@fedify/fixture";
11
11
  import { Create, DataIntegrityProof, Multikey, Note, Place } from "@fedify/vocab";
12
12
  import { decodeMultibase, importMultibaseKey } from "@fedify/vocab-runtime";