@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.
- package/dist/assert_strict_equals-Dmjbg-bA.mjs +41 -0
- package/dist/{builder-BfmqkrIE.mjs → builder-OFkoAQ85.mjs} +3 -3
- package/dist/compat/mod.d.cts +1 -1
- package/dist/compat/mod.d.ts +1 -1
- package/dist/compat/outgoing-jsonld.test.d.mts +2 -0
- package/dist/compat/outgoing-jsonld.test.mjs +189 -0
- package/dist/compat/public-audience.test.d.mts +2 -0
- package/dist/compat/public-audience.test.mjs +178 -0
- package/dist/compat/transformers.test.mjs +3 -3
- package/dist/{context-BGrYMSTk.d.ts → context-BzH2-ajs.d.ts} +22 -0
- package/dist/{context-CMUd4wy0.d.cts → context-DJGagtNd.d.cts} +22 -0
- package/dist/{deno-CjZGHpS5.mjs → deno-BYRjHaeb.mjs} +1 -1
- package/dist/{docloader-Du9_2PyA.mjs → docloader-CuVh02a1.mjs} +2 -2
- package/dist/federation/builder.test.mjs +3 -3
- package/dist/federation/collection.test.mjs +2 -2
- package/dist/federation/handler.test.mjs +8 -8
- package/dist/federation/idempotency.test.mjs +5 -5
- package/dist/federation/inbox.test.mjs +1 -1
- package/dist/federation/keycache.test.mjs +3 -3
- package/dist/federation/kv.test.mjs +2 -2
- package/dist/federation/middleware.test.mjs +160 -10
- package/dist/federation/mod.cjs +1 -1
- package/dist/federation/mod.d.cts +2 -2
- package/dist/federation/mod.d.ts +2 -2
- package/dist/federation/mod.js +1 -1
- package/dist/federation/mq.test.mjs +17 -10
- package/dist/federation/negotiation.test.mjs +3 -3
- package/dist/federation/retry.test.mjs +1 -1
- package/dist/federation/router.test.mjs +2 -2
- package/dist/federation/send.test.mjs +6 -6
- package/dist/federation/webfinger.test.mjs +3 -3
- package/dist/{http-9zjtsC0n.mjs → http-BrVfkREl.mjs} +3 -3
- package/dist/{http-Wm7tvhRa.cjs → http-H-4FzBb3.cjs} +1 -1
- package/dist/{http-C8puyZ4Z.js → http-pZce7PcA.js} +1 -1
- package/dist/{key-CMhIdO1-.mjs → key-cK-YTNKa.mjs} +1 -1
- package/dist/{kv-cache-BTq6qqgJ.js → kv-cache-CjweM0Am.js} +1 -1
- package/dist/{kv-cache-DyRjARFV.cjs → kv-cache-NgzTkTjv.cjs} +1 -1
- package/dist/{ld-BH-6muxq.mjs → ld-SXDkzuUo.mjs} +2 -2
- package/dist/{middleware-CO5RpqOP.mjs → middleware-AqjYcDmu.mjs} +1 -1
- package/dist/{middleware-DBgitte6.mjs → middleware-BMePykoo.mjs} +34 -22
- package/dist/{middleware-D3S_Ctwx.cjs → middleware-CXhCkBG4.cjs} +1 -1
- package/dist/{middleware-C_CRggCg.cjs → middleware-TZHT1gKk.cjs} +20 -9
- package/dist/{middleware-Da-j6H9U.js → middleware-YcQIUUHs.js} +19 -8
- package/dist/{mod-CJXfyw7v.d.ts → mod-2d12ffz3.d.ts} +1 -1
- package/dist/{mod-BcJHeuv1.d.cts → mod-D35TRn09.d.cts} +1 -1
- package/dist/mod.cjs +4 -4
- package/dist/mod.d.cts +2 -2
- package/dist/mod.d.ts +2 -2
- package/dist/mod.js +4 -4
- package/dist/nodeinfo/client.test.mjs +2 -2
- package/dist/nodeinfo/handler.test.mjs +3 -3
- package/dist/nodeinfo/types.test.mjs +2 -2
- package/dist/otel/exporter.test.mjs +2 -2
- package/dist/outgoing-jsonld-CNmZLixq.mjs +203 -0
- package/dist/{owner-CE5FwvNR.mjs → owner-Cudh-ej0.mjs} +2 -2
- package/dist/{proof-jHDv7IKD.js → proof-BJrEACyu.js} +425 -41
- package/dist/{proof-D-HuDCQe.cjs → proof-CFERN43j.cjs} +428 -38
- package/dist/{proof-Ds3T1-sE.mjs → proof-DC69vtxY.mjs} +38 -31
- package/dist/public-audience-DYFHzm_c.mjs +192 -0
- package/dist/{send-TicMA6nJ.mjs → send-BBRG1CKC.mjs} +2 -2
- package/dist/sig/accept.test.mjs +1 -1
- package/dist/sig/http.test.mjs +5 -5
- package/dist/sig/key.test.mjs +3 -3
- package/dist/sig/ld.test.mjs +4 -4
- package/dist/sig/mod.cjs +2 -2
- package/dist/sig/mod.js +2 -2
- package/dist/sig/owner.test.mjs +4 -4
- package/dist/sig/proof.test.mjs +78 -5
- package/dist/{std__assert-Duiq_YC9.mjs → std__assert-CRDpx_HF.mjs} +3 -38
- package/dist/testing/mod.d.mts +22 -0
- package/dist/utils/docloader.test.mjs +4 -4
- package/dist/utils/kv-cache.test.mjs +1 -1
- package/dist/utils/mod.cjs +1 -1
- package/dist/utils/mod.js +1 -1
- package/package.json +5 -5
- /package/dist/{accept-Dd__NiUL.mjs → accept-CPkZzmGN.mjs} +0 -0
- /package/dist/{activity-listener-Ck3JZ_hR.mjs → activity-listener-ell7W1s9.mjs} +0 -0
- /package/dist/{assert-ddO5KLpe.mjs → assert-DikXweDx.mjs} +0 -0
- /package/dist/{client-DEpOVgY1.mjs → client-D_1QpnWt.mjs} +0 -0
- /package/dist/{collection-BD6-SZ6O.mjs → collection-D-HqUuA2.mjs} +0 -0
- /package/dist/{keycache-CCSwkQcY.mjs → keycache-EGATflN-.mjs} +0 -0
- /package/dist/{keys-BAK-tUlf.mjs → keys-DGu1NFwu.mjs} +0 -0
- /package/dist/{kv-cache-B01V7s3h.mjs → kv-cache-U__xU4qR.mjs} +0 -0
- /package/dist/{kv-tL2TOE9X.mjs → kv-rV3vodCc.mjs} +0 -0
- /package/dist/{negotiation-DnsfFF8I.mjs → negotiation-SQvQgUqe.mjs} +0 -0
- /package/dist/{retry-B_E3V_Dx.mjs → retry-bMXBL97A.mjs} +0 -0
- /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-
|
|
5
|
-
import "./key-
|
|
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";
|