@fedify/fedify 2.2.0-pr.715.28 → 2.2.0-pr.731.34

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 (87) hide show
  1. package/dist/assert_strict_equals-Dmjbg-bA.mjs +41 -0
  2. package/dist/{builder-BfmqkrIE.mjs → builder-OFkoAQ85.mjs} +3 -3
  3. package/dist/compat/mod.d.cts +1 -1
  4. package/dist/compat/mod.d.ts +1 -1
  5. package/dist/compat/outgoing-jsonld.test.d.mts +2 -0
  6. package/dist/compat/outgoing-jsonld.test.mjs +189 -0
  7. package/dist/compat/public-audience.test.d.mts +2 -0
  8. package/dist/compat/public-audience.test.mjs +178 -0
  9. package/dist/compat/transformers.test.mjs +3 -3
  10. package/dist/{context-BGrYMSTk.d.ts → context-BzH2-ajs.d.ts} +22 -0
  11. package/dist/{context-CMUd4wy0.d.cts → context-DJGagtNd.d.cts} +22 -0
  12. package/dist/{deno-CjZGHpS5.mjs → deno-BYRjHaeb.mjs} +1 -1
  13. package/dist/{docloader-Du9_2PyA.mjs → docloader-CuVh02a1.mjs} +2 -2
  14. package/dist/federation/builder.test.mjs +3 -3
  15. package/dist/federation/collection.test.mjs +2 -2
  16. package/dist/federation/handler.test.mjs +8 -8
  17. package/dist/federation/idempotency.test.mjs +5 -5
  18. package/dist/federation/inbox.test.mjs +1 -1
  19. package/dist/federation/keycache.test.mjs +3 -3
  20. package/dist/federation/kv.test.mjs +2 -2
  21. package/dist/federation/middleware.test.mjs +160 -10
  22. package/dist/federation/mod.cjs +1 -1
  23. package/dist/federation/mod.d.cts +2 -2
  24. package/dist/federation/mod.d.ts +2 -2
  25. package/dist/federation/mod.js +1 -1
  26. package/dist/federation/mq.test.mjs +17 -10
  27. package/dist/federation/negotiation.test.mjs +3 -3
  28. package/dist/federation/retry.test.mjs +1 -1
  29. package/dist/federation/router.test.mjs +2 -2
  30. package/dist/federation/send.test.mjs +6 -6
  31. package/dist/federation/webfinger.test.mjs +3 -3
  32. package/dist/{http-9zjtsC0n.mjs → http-BrVfkREl.mjs} +3 -3
  33. package/dist/{http-Wm7tvhRa.cjs → http-H-4FzBb3.cjs} +1 -1
  34. package/dist/{http-C8puyZ4Z.js → http-pZce7PcA.js} +1 -1
  35. package/dist/{key-CMhIdO1-.mjs → key-cK-YTNKa.mjs} +1 -1
  36. package/dist/{kv-cache-BTq6qqgJ.js → kv-cache-CjweM0Am.js} +1 -1
  37. package/dist/{kv-cache-DyRjARFV.cjs → kv-cache-NgzTkTjv.cjs} +1 -1
  38. package/dist/{ld-BH-6muxq.mjs → ld-SXDkzuUo.mjs} +2 -2
  39. package/dist/{middleware-CO5RpqOP.mjs → middleware-AqjYcDmu.mjs} +1 -1
  40. package/dist/{middleware-DBgitte6.mjs → middleware-BMePykoo.mjs} +34 -22
  41. package/dist/{middleware-D3S_Ctwx.cjs → middleware-CXhCkBG4.cjs} +1 -1
  42. package/dist/{middleware-C_CRggCg.cjs → middleware-TZHT1gKk.cjs} +20 -9
  43. package/dist/{middleware-Da-j6H9U.js → middleware-YcQIUUHs.js} +19 -8
  44. package/dist/{mod-CJXfyw7v.d.ts → mod-2d12ffz3.d.ts} +1 -1
  45. package/dist/{mod-BcJHeuv1.d.cts → mod-D35TRn09.d.cts} +1 -1
  46. package/dist/mod.cjs +4 -4
  47. package/dist/mod.d.cts +2 -2
  48. package/dist/mod.d.ts +2 -2
  49. package/dist/mod.js +4 -4
  50. package/dist/nodeinfo/client.test.mjs +2 -2
  51. package/dist/nodeinfo/handler.test.mjs +3 -3
  52. package/dist/nodeinfo/types.test.mjs +2 -2
  53. package/dist/otel/exporter.test.mjs +2 -2
  54. package/dist/outgoing-jsonld-CNmZLixq.mjs +203 -0
  55. package/dist/{owner-CE5FwvNR.mjs → owner-Cudh-ej0.mjs} +2 -2
  56. package/dist/{proof-jHDv7IKD.js → proof-BJrEACyu.js} +425 -41
  57. package/dist/{proof-D-HuDCQe.cjs → proof-CFERN43j.cjs} +428 -38
  58. package/dist/{proof-Ds3T1-sE.mjs → proof-DC69vtxY.mjs} +38 -31
  59. package/dist/public-audience-DYFHzm_c.mjs +192 -0
  60. package/dist/{send-TicMA6nJ.mjs → send-BBRG1CKC.mjs} +2 -2
  61. package/dist/sig/accept.test.mjs +1 -1
  62. package/dist/sig/http.test.mjs +5 -5
  63. package/dist/sig/key.test.mjs +3 -3
  64. package/dist/sig/ld.test.mjs +4 -4
  65. package/dist/sig/mod.cjs +2 -2
  66. package/dist/sig/mod.js +2 -2
  67. package/dist/sig/owner.test.mjs +4 -4
  68. package/dist/sig/proof.test.mjs +78 -5
  69. package/dist/{std__assert-Duiq_YC9.mjs → std__assert-CRDpx_HF.mjs} +3 -38
  70. package/dist/testing/mod.d.mts +22 -0
  71. package/dist/utils/docloader.test.mjs +4 -4
  72. package/dist/utils/kv-cache.test.mjs +1 -1
  73. package/dist/utils/mod.cjs +1 -1
  74. package/dist/utils/mod.js +1 -1
  75. package/package.json +5 -5
  76. /package/dist/{accept-Dd__NiUL.mjs → accept-CPkZzmGN.mjs} +0 -0
  77. /package/dist/{activity-listener-Ck3JZ_hR.mjs → activity-listener-ell7W1s9.mjs} +0 -0
  78. /package/dist/{assert-ddO5KLpe.mjs → assert-DikXweDx.mjs} +0 -0
  79. /package/dist/{client-DEpOVgY1.mjs → client-D_1QpnWt.mjs} +0 -0
  80. /package/dist/{collection-BD6-SZ6O.mjs → collection-D-HqUuA2.mjs} +0 -0
  81. /package/dist/{keycache-CCSwkQcY.mjs → keycache-EGATflN-.mjs} +0 -0
  82. /package/dist/{keys-BAK-tUlf.mjs → keys-DGu1NFwu.mjs} +0 -0
  83. /package/dist/{kv-cache-B01V7s3h.mjs → kv-cache-U__xU4qR.mjs} +0 -0
  84. /package/dist/{kv-tL2TOE9X.mjs → kv-rV3vodCc.mjs} +0 -0
  85. /package/dist/{negotiation-DnsfFF8I.mjs → negotiation-SQvQgUqe.mjs} +0 -0
  86. /package/dist/{retry-B_E3V_Dx.mjs → retry-bMXBL97A.mjs} +0 -0
  87. /package/dist/{types-DCP0WLdt.mjs → types-J53Kw7so.mjs} +0 -0
@@ -0,0 +1,203 @@
1
+ import "@js-temporal/polyfill";
2
+ import "urlpattern-polyfill";
3
+ globalThis.addEventListener = () => {};
4
+ import { n as preloadedOnlyDocumentLoader, t as normalizePublicAudience } from "./public-audience-DYFHzm_c.mjs";
5
+ import { preloadedContexts } from "@fedify/vocab-runtime";
6
+ import { getLogger } from "@logtape/logtape";
7
+ import jsonld from "@fedify/vocab-runtime/jsonld";
8
+ //#region src/compat/outgoing-jsonld.ts
9
+ const logger = getLogger([
10
+ "fedify",
11
+ "compat",
12
+ "outgoing-jsonld"
13
+ ]);
14
+ const ATTACHMENT_FIELDS = new Set(["attachment", "https://www.w3.org/ns/activitystreams#attachment"]);
15
+ const AS_CONTEXT_URL = "https://www.w3.org/ns/activitystreams";
16
+ const KNOWN_SAFE_CONTEXT_URLS = getKnownSafeContextUrls();
17
+ const MAX_TRAVERSAL_DEPTH = 64;
18
+ function isJsonLdListObject(value) {
19
+ return typeof value === "object" && value != null && Object.hasOwn(value, "@list");
20
+ }
21
+ function isJsonLdValueObject(value) {
22
+ return typeof value === "object" && value != null && Object.hasOwn(value, "@value");
23
+ }
24
+ function* getContextObjects(value, seen = /* @__PURE__ */ new WeakSet()) {
25
+ if (Array.isArray(value)) {
26
+ if (seen.has(value)) return;
27
+ seen.add(value);
28
+ for (const item of value) yield* getContextObjects(item, seen);
29
+ return;
30
+ }
31
+ if (typeof value === "object" && value != null) {
32
+ if (seen.has(value)) return;
33
+ seen.add(value);
34
+ const record = value;
35
+ yield record;
36
+ for (const definition of Object.values(record)) {
37
+ if (typeof definition !== "object" || definition == null) continue;
38
+ const nestedContext = definition["@context"];
39
+ if (nestedContext == null) continue;
40
+ yield* getContextObjects(nestedContext, seen);
41
+ }
42
+ }
43
+ }
44
+ function isActivityStreamsAttachmentTerm(value) {
45
+ return typeof value === "object" && value != null && value["@id"] === "as:attachment" && value["@type"] === "@id";
46
+ }
47
+ /** @internal */
48
+ function isPreloadedContextAttachmentSafe(document) {
49
+ if (typeof document !== "object" || document == null) return true;
50
+ const context = document["@context"];
51
+ for (const contextObject of getContextObjects(context)) {
52
+ if (!Object.hasOwn(contextObject, "attachment")) continue;
53
+ if (isActivityStreamsAttachmentTerm(contextObject.attachment)) continue;
54
+ return false;
55
+ }
56
+ return true;
57
+ }
58
+ function getKnownSafeContextUrls() {
59
+ const urls = /* @__PURE__ */ new Set();
60
+ for (const [url, document] of Object.entries(preloadedContexts)) if (isPreloadedContextAttachmentSafe(document)) urls.add(url);
61
+ else logger.warn("Preloaded JSON-LD context {contextUrl} redefines the `attachment` term incompatibly; attachment array normalization will require canonicalization for documents using it.", { contextUrl: url });
62
+ return urls;
63
+ }
64
+ /**
65
+ * Wraps scalar ActivityStreams attachment properties in arrays.
66
+ */
67
+ function wrapScalarAttachments(jsonLd, depth = 0) {
68
+ if (depth >= MAX_TRAVERSAL_DEPTH) return jsonLd;
69
+ if (Array.isArray(jsonLd)) {
70
+ let normalized = null;
71
+ for (let i = 0; i < jsonLd.length; i++) {
72
+ const item = jsonLd[i];
73
+ const next = wrapScalarAttachments(item, depth + 1);
74
+ if (normalized == null && next !== item) normalized = jsonLd.slice(0, i);
75
+ if (normalized != null) normalized[i] = next;
76
+ }
77
+ return normalized ?? jsonLd;
78
+ }
79
+ if (typeof jsonLd !== "object" || jsonLd == null) return jsonLd;
80
+ const record = jsonLd;
81
+ const keys = Object.keys(record);
82
+ let normalized = null;
83
+ for (let i = 0; i < keys.length; i++) {
84
+ const key = keys[i];
85
+ const value = record[key];
86
+ const next = key === "@context" || key === "@value" && isJsonLdValueObject(jsonLd) ? value : wrapScalarAttachments(value, depth + 1);
87
+ const output = ATTACHMENT_FIELDS.has(key) && next != null && !Array.isArray(next) && !isJsonLdListObject(next) ? [next] : next;
88
+ if (normalized == null && output !== value) {
89
+ const cloned = Object.create(null);
90
+ for (let j = 0; j < i; j++) {
91
+ const previousKey = keys[j];
92
+ cloned[previousKey] = record[previousKey];
93
+ }
94
+ normalized = cloned;
95
+ }
96
+ if (normalized != null) normalized[key] = output;
97
+ }
98
+ return normalized ?? jsonLd;
99
+ }
100
+ function hasNestedContext(value, depth = 0) {
101
+ if (depth >= MAX_TRAVERSAL_DEPTH) return true;
102
+ if (Array.isArray(value)) return value.some((item) => hasNestedContext(item, depth + 1));
103
+ if (typeof value !== "object" || value == null) return false;
104
+ const record = value;
105
+ for (const key of Object.keys(record)) {
106
+ if (key === "@context") return true;
107
+ if (key === "@value" && isJsonLdValueObject(value)) continue;
108
+ if (hasNestedContext(record[key], depth + 1)) return true;
109
+ }
110
+ return false;
111
+ }
112
+ function exceedsTraversalDepth(value, depth = 0) {
113
+ if (depth >= MAX_TRAVERSAL_DEPTH) return true;
114
+ if (Array.isArray(value)) return value.some((item) => exceedsTraversalDepth(item, depth + 1));
115
+ if (typeof value !== "object" || value == null) return false;
116
+ const record = value;
117
+ for (const key of Object.keys(record)) {
118
+ if (key === "@context" || key === "@value" && isJsonLdValueObject(value)) continue;
119
+ if (exceedsTraversalDepth(record[key], depth + 1)) return true;
120
+ }
121
+ return false;
122
+ }
123
+ function hasKnownSafeContext(jsonLd) {
124
+ if (typeof jsonLd !== "object" || jsonLd == null) return false;
125
+ const record = jsonLd;
126
+ if (!Object.hasOwn(record, "@context")) return false;
127
+ const context = record["@context"];
128
+ const entries = typeof context === "string" ? [context] : Array.isArray(context) ? context : null;
129
+ if (entries == null || entries.length < 1) return false;
130
+ let hasActivityStreamsContext = false;
131
+ for (const entry of entries) {
132
+ if (typeof entry !== "string") return false;
133
+ if (!KNOWN_SAFE_CONTEXT_URLS.has(entry)) return false;
134
+ if (entry === AS_CONTEXT_URL) hasActivityStreamsContext = true;
135
+ }
136
+ if (!hasActivityStreamsContext) return false;
137
+ for (const key of Object.keys(record)) {
138
+ if (key === "@context") continue;
139
+ if (hasNestedContext(record[key])) return false;
140
+ }
141
+ return true;
142
+ }
143
+ function getLogSafeJsonLdMetadata(jsonLd) {
144
+ if (typeof jsonLd !== "object" || jsonLd == null) return {};
145
+ const record = jsonLd;
146
+ const context = record["@context"];
147
+ return {
148
+ id: typeof record.id === "string" ? record.id : typeof record["@id"] === "string" ? record["@id"] : void 0,
149
+ type: typeof record.type === "string" ? record.type : typeof record["@type"] === "string" ? record["@type"] : void 0,
150
+ context: typeof context === "string" ? context : Array.isArray(context) ? context.filter((entry) => typeof entry === "string").slice(0, 4) : context == null ? void 0 : "[inline context]"
151
+ };
152
+ }
153
+ /**
154
+ * Ensures ActivityStreams attachment properties are represented as arrays
155
+ * when doing so preserves the JSON-LD semantics.
156
+ *
157
+ * JSON-LD compaction collapses single-item arrays into scalar values by
158
+ * default. Some ActivityPub implementations, Pixelfed among them, parse
159
+ * `attachment` as a plain JSON array rather than a JSON-LD property and reject
160
+ * otherwise valid objects whose single attachment is emitted as a scalar.
161
+ *
162
+ * When no `contextLoader` is supplied, the helper falls back to a restricted
163
+ * loader that resolves only Fedify's preloaded JSON-LD contexts and rejects
164
+ * every other URL without network access. Documents with custom, inline, or
165
+ * otherwise uncached contexts should pass a real `contextLoader` if they need
166
+ * the semantic-preservation check to succeed; otherwise canonicalization
167
+ * failures leave the original document unchanged.
168
+ */
169
+ async function normalizeAttachmentArrays(jsonLd, contextLoader) {
170
+ const normalized = wrapScalarAttachments(jsonLd);
171
+ if (normalized === jsonLd) return jsonLd;
172
+ if (exceedsTraversalDepth(jsonLd)) {
173
+ logger.debug("Skipping attachment array normalization because the JSON-LD document exceeds the safe traversal depth; leaving it unchanged.");
174
+ return jsonLd;
175
+ }
176
+ if (hasKnownSafeContext(jsonLd)) return normalized;
177
+ const loader = contextLoader ?? preloadedOnlyDocumentLoader;
178
+ try {
179
+ const [before, after] = await Promise.all([jsonld.canonize(jsonLd, {
180
+ format: "application/n-quads",
181
+ documentLoader: loader
182
+ }), jsonld.canonize(normalized, {
183
+ format: "application/n-quads",
184
+ documentLoader: loader
185
+ })]);
186
+ if (before === after) return normalized;
187
+ logger.warn("Wrapping scalar attachment values in arrays would change the canonical form of the JSON-LD document; leaving it unchanged. This usually means the active JSON-LD context redefines the `attachment` term. Document: {id}; type: {type}; context: {context}.", getLogSafeJsonLdMetadata(jsonLd));
188
+ } catch (error) {
189
+ logger.debug("Failed to verify attachment array normalization equivalence via JSON-LD canonicalization; leaving the JSON-LD document unchanged.\n{error}", { error });
190
+ }
191
+ return jsonLd;
192
+ }
193
+ /**
194
+ * Applies Fedify's internal JSON-LD wire-format interoperability workarounds
195
+ * to locally generated outgoing activities before they are signed, enqueued,
196
+ * or sent.
197
+ */
198
+ async function normalizeOutgoingActivityJsonLd(jsonLd, contextLoader) {
199
+ jsonLd = await normalizePublicAudience(jsonLd, contextLoader);
200
+ return await normalizeAttachmentArrays(jsonLd, contextLoader);
201
+ }
202
+ //#endregion
203
+ export { normalizeAttachmentArrays as n, normalizeOutgoingActivityJsonLd as r, isPreloadedContextAttachmentSafe as t };
@@ -1,8 +1,8 @@
1
1
  import "@js-temporal/polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-CjZGHpS5.mjs";
5
- import "./key-CMhIdO1-.mjs";
4
+ import { n as version, t as name } from "./deno-BYRjHaeb.mjs";
5
+ import "./key-cK-YTNKa.mjs";
6
6
  import { CryptographicKey, Object as Object$1, isActor } from "@fedify/vocab";
7
7
  import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
8
8
  import { getDocumentLoader } from "@fedify/vocab-runtime";