@fedify/fedify 2.0.17-dev.1093 → 2.0.18

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-CoG4VXAS.mjs → builder-CtrAeTRY.mjs} +3 -3
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{context-BzRJ49gL.d.cts → context-CJZHWLmz.d.cts} +48 -6
  6. package/dist/{context-CdJ9wAQa.d.ts → context-DnsFj3yK.d.ts} +48 -6
  7. package/dist/{deno-BsTAaG38.mjs → deno-mPpS1a5z.mjs} +1 -1
  8. package/dist/{docloader-BpyzfTRB.mjs → docloader-B-SKc43w.mjs} +2 -2
  9. package/dist/federation/builder.test.mjs +1 -1
  10. package/dist/federation/handler.test.mjs +1358 -41
  11. package/dist/federation/idempotency.test.mjs +2 -2
  12. package/dist/federation/inbox.test.mjs +1 -1
  13. package/dist/federation/middleware.test.mjs +1588 -84
  14. package/dist/federation/mod.cjs +1 -1
  15. package/dist/federation/mod.d.cts +2 -2
  16. package/dist/federation/mod.d.ts +2 -2
  17. package/dist/federation/mod.js +1 -1
  18. package/dist/federation/retry.test.mjs +1 -1
  19. package/dist/federation/send.test.mjs +3 -3
  20. package/dist/federation/temporal.test.d.mts +2 -0
  21. package/dist/federation/temporal.test.mjs +71 -0
  22. package/dist/federation/webfinger.test.mjs +1 -1
  23. package/dist/{http-ejFBVI1I.cjs → http-BL8JVR8k.cjs} +1 -1
  24. package/dist/{http-DBHhHcMm.js → http-C3tabf9n.js} +1 -1
  25. package/dist/{http-ClOkZPVk.mjs → http-CEsXGtbz.mjs} +2 -2
  26. package/dist/{inbox-1iBLYwIM.mjs → inbox-Tsb61Zs7.mjs} +7 -4
  27. package/dist/{key-DgnaBuPQ.mjs → key-BaYP-_dg.mjs} +1 -1
  28. package/dist/{kv-cache-BbfOz_6f.cjs → kv-cache-BsgxbwLm.cjs} +1 -1
  29. package/dist/{kv-cache-eO0dIiEK.js → kv-cache-Dbi0W6UJ.js} +1 -1
  30. package/dist/ld-CAaJNVwd.mjs +550 -0
  31. package/dist/{middleware-Cg0vLx3s.js → middleware-B3xIsf51.js} +396 -71
  32. package/dist/{middleware-C1lbrpLn.mjs → middleware-CXy6C5p8.mjs} +1 -1
  33. package/dist/{middleware-CML7W6o9.cjs → middleware-CmqvwFWM.cjs} +399 -73
  34. package/dist/{middleware-EM8jlXPc.cjs → middleware-DXrzwPDQ.cjs} +1 -1
  35. package/dist/{middleware-CM-lm1Ow.mjs → middleware-qU3blEV5.mjs} +309 -76
  36. package/dist/{mod-CKkpvznG.d.cts → mod-43DJyETz.d.cts} +1 -1
  37. package/dist/{mod-Kzr52ns8.d.ts → mod-COgmn-UO.d.ts} +1 -1
  38. package/dist/mod.cjs +4 -4
  39. package/dist/mod.d.cts +2 -2
  40. package/dist/mod.d.ts +2 -2
  41. package/dist/mod.js +4 -4
  42. package/dist/nodeinfo/handler.test.mjs +1 -1
  43. package/dist/{owner--l5W54LY.mjs → owner-DdHZSQaN.mjs} +2 -2
  44. package/dist/{proof-CJ04SPrP.mjs → proof-Cr7l6UvL.mjs} +2 -2
  45. package/dist/{proof-DNpSHLPH.cjs → proof-DTHPJVvm.cjs} +345 -3
  46. package/dist/{proof-C2fn-J-1.js → proof-wXzMwWVt.js} +298 -4
  47. package/dist/{send-BTHdq66r.mjs → send-ChZJgc6Y.mjs} +2 -2
  48. package/dist/sig/http.test.mjs +2 -2
  49. package/dist/sig/key.test.mjs +1 -1
  50. package/dist/sig/ld.test.mjs +558 -2
  51. package/dist/sig/mod.cjs +2 -2
  52. package/dist/sig/mod.js +2 -2
  53. package/dist/sig/owner.test.mjs +1 -1
  54. package/dist/sig/proof.test.mjs +1 -1
  55. package/dist/temporal-Bxr6zsNS.mjs +95 -0
  56. package/dist/testing/mod.d.mts +48 -6
  57. package/dist/utils/docloader.test.mjs +2 -2
  58. package/dist/utils/mod.cjs +1 -1
  59. package/dist/utils/mod.js +1 -1
  60. package/package.json +5 -5
  61. package/dist/ld-DQmBISTI.mjs +0 -256
  62. /package/dist/{retry-Ddbq3AcK.mjs → retry-B_E3V_Dx.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 { r as generateCryptoKeyPair } from "../key-DgnaBuPQ.mjs";
8
+ import { r as generateCryptoKeyPair } from "../key-BaYP-_dg.mjs";
9
9
  import { a as rsaPrivateKey3, c as rsaPublicKey3, i as rsaPrivateKey2, n as ed25519PrivateKey, s as rsaPublicKey2, t as ed25519Multikey } from "../keys-CtZLJq76.mjs";
10
- import { a as signJsonLd, n as createSignature, o as verifyJsonLd, r as detachSignature, s as verifySignature, t as attachSignature } from "../ld-DQmBISTI.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-CAaJNVwd.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-ejFBVI1I.cjs");
5
- const require_proof = require("../proof-DNpSHLPH.cjs");
4
+ const require_http = require("../http-BL8JVR8k.cjs");
5
+ const require_proof = require("../proof-DTHPJVvm.cjs");
6
6
  exports.attachSignature = require_proof.attachSignature;
7
7
  exports.createProof = require_proof.createProof;
8
8
  exports.createSignature = require_proof.createSignature;
package/dist/sig/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Temporal } from "@js-temporal/polyfill";
2
2
  import { URLPattern } from "urlpattern-polyfill";
3
- import { a as fetchKey, i as exportJwk, n as signRequest, o as generateCryptoKeyPair, r as verifyRequest, s as importJwk } from "../http-DBHhHcMm.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-C2fn-J-1.js";
3
+ import { a as fetchKey, i as exportJwk, n as signRequest, o as generateCryptoKeyPair, r as verifyRequest, s as importJwk } from "../http-C3tabf9n.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-wXzMwWVt.js";
5
5
  export { attachSignature, createProof, createSignature, detachSignature, doesActorOwnKey, exportJwk, fetchKey, generateCryptoKeyPair, getKeyOwner, importJwk, signJsonLd, signObject, signRequest, verifyJsonLd, verifyObject, verifyProof, verifyRequest, 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-CtZLJq76.mjs";
9
- import { n as getKeyOwner, t as doesActorOwnKey } from "../owner--l5W54LY.mjs";
9
+ import { n as getKeyOwner, t as doesActorOwnKey } from "../owner-DdHZSQaN.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-CtZLJq76.mjs";
9
- import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-CJ04SPrP.mjs";
9
+ import { i as verifyProof, n as signObject, r as verifyObject, t as createProof } from "../proof-Cr7l6UvL.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";