@fedify/vocab 2.4.5-dev.2453 → 2.4.5
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/deno.json +1 -1
- package/dist/mod.cjs +80 -3
- package/dist/mod.d.cts +75 -0
- package/dist/mod.d.ts +75 -0
- package/dist/mod.js +80 -3
- package/dist-tests/{actor-BejKRRoq.mjs → actor-BWv7I2WQ.mjs} +6 -4
- package/dist-tests/actor.test.mjs +4 -3
- package/dist-tests/{esm-B55wgjAT.mjs → esm-BIqRhjGA.mjs} +1 -1
- package/dist-tests/gateway.test.mjs +4 -4
- package/dist-tests/{lookup-Bhab3PNj.mjs → lookup---G_JdKW.mjs} +2 -2
- package/dist-tests/lookup.test.mjs +35 -15
- package/dist-tests/portable-lookup.test.mjs +52 -13
- package/dist-tests/rolldown-runtime-BWJg4WE8.mjs +37 -0
- package/dist-tests/signed-representation.test.mjs +1 -1
- package/dist-tests/translation.test.mjs +3 -3
- package/dist-tests/type.test.mjs +1 -1
- package/dist-tests/undici-D88PC0XH.mjs +22898 -0
- package/dist-tests/{vocab-mc4pgfni.mjs → vocab-S9K4rFgH.mjs} +77 -34
- package/dist-tests/vocab.test.mjs +6064 -8
- package/package.json +5 -5
- package/src/actor.ts +4 -0
- package/src/gateway.test.ts +1 -1
- package/src/lookup.test.ts +37 -11
- package/src/portable-lookup.test.ts +72 -7
- package/src/vocab.test.ts +40 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab",
|
|
3
|
-
"version": "2.4.5
|
|
3
|
+
"version": "2.4.5",
|
|
4
4
|
"homepage": "https://fedify.dev/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@multiformats/base-x": "^4.0.1",
|
|
39
39
|
"@logtape/logtape": "^2.2.0",
|
|
40
|
-
"@opentelemetry/api": "
|
|
40
|
+
"@opentelemetry/api": "~1.9.1",
|
|
41
41
|
"asn1js": "^3.0.10",
|
|
42
42
|
"es-toolkit": "1.46.1",
|
|
43
43
|
"jsonld": "^9.0.0",
|
|
44
44
|
"pkijs": "^3.3.3",
|
|
45
45
|
"temporal-polyfill": "^1.0.1",
|
|
46
|
-
"@fedify/vocab-tools": "2.4.5
|
|
47
|
-
"@fedify/
|
|
48
|
-
"@fedify/
|
|
46
|
+
"@fedify/vocab-tools": "2.4.5",
|
|
47
|
+
"@fedify/vocab-runtime": "2.4.5",
|
|
48
|
+
"@fedify/webfinger": "2.4.5"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.12.2",
|
package/src/actor.ts
CHANGED
|
@@ -394,6 +394,8 @@ async function getPortableActorHandle(
|
|
|
394
394
|
userAgent: options.userAgent,
|
|
395
395
|
tracerProvider: options.tracerProvider,
|
|
396
396
|
meterProvider: options.meterProvider,
|
|
397
|
+
allowPrivateAddress: "allowPrivateAddress" in options &&
|
|
398
|
+
options.allowPrivateAddress === true,
|
|
397
399
|
});
|
|
398
400
|
// Unlike an ordinary actor, whose ID vouches for its host, a portable
|
|
399
401
|
// actor's gateways are claimed by the actor itself, so there is no
|
|
@@ -409,6 +411,8 @@ async function getPortableActorHandle(
|
|
|
409
411
|
userAgent: options.userAgent,
|
|
410
412
|
tracerProvider: options.tracerProvider,
|
|
411
413
|
meterProvider: options.meterProvider,
|
|
414
|
+
allowPrivateAddress: "allowPrivateAddress" in options &&
|
|
415
|
+
options.allowPrivateAddress === true,
|
|
412
416
|
});
|
|
413
417
|
if (
|
|
414
418
|
subjectResult != null && linksToPortableActor(subjectResult, canonicalId)
|
package/src/gateway.test.ts
CHANGED
|
@@ -876,7 +876,7 @@ test("getObject() sends the ActivityStreams Accept header to gateways", {
|
|
|
876
876
|
});
|
|
877
877
|
try {
|
|
878
878
|
const object = await (await createActivity()).getObject({
|
|
879
|
-
documentLoader: getDocumentLoader(),
|
|
879
|
+
documentLoader: getDocumentLoader({ allowPrivateAddress: true }),
|
|
880
880
|
contextLoader: mockDocumentLoader,
|
|
881
881
|
gateways: ["https://example.com"],
|
|
882
882
|
verifyPortableObject: createVerifier(),
|
package/src/lookup.test.ts
CHANGED
|
@@ -10,10 +10,17 @@ import { lookupObject, traverseCollection } from "./lookup.ts";
|
|
|
10
10
|
import { assertInstanceOf } from "./utils.ts";
|
|
11
11
|
import { Collection, Note, Object, Person } from "./vocab.ts";
|
|
12
12
|
|
|
13
|
+
// lookupObject() accepts this option without declaring it, since Fedify's
|
|
14
|
+
// Context passes it. It makes WebFinger lookups use the global fetch()
|
|
15
|
+
// (fetch-mock here) without resolving hostnames, so that the tests do not
|
|
16
|
+
// depend on the real DNS:
|
|
17
|
+
const allowPrivateAddress = { allowPrivateAddress: true };
|
|
18
|
+
|
|
13
19
|
test("lookupObject()", {
|
|
14
20
|
sanitizeResources: false,
|
|
15
21
|
sanitizeOps: false,
|
|
16
22
|
}, async (t) => {
|
|
23
|
+
const responseTimers: ReturnType<typeof setTimeout>[] = [];
|
|
17
24
|
fetchMock.spyGlobal();
|
|
18
25
|
|
|
19
26
|
fetchMock.get(
|
|
@@ -43,6 +50,7 @@ test("lookupObject()", {
|
|
|
43
50
|
const options = {
|
|
44
51
|
documentLoader: mockDocumentLoader,
|
|
45
52
|
contextLoader: mockDocumentLoader,
|
|
53
|
+
...allowPrivateAddress,
|
|
46
54
|
};
|
|
47
55
|
|
|
48
56
|
await t.step("actor", async () => {
|
|
@@ -106,7 +114,7 @@ test("lookupObject()", {
|
|
|
106
114
|
"begin:https://example.com/.well-known/webfinger",
|
|
107
115
|
() =>
|
|
108
116
|
new Promise((resolve) => {
|
|
109
|
-
setTimeout(() => {
|
|
117
|
+
responseTimers.push(setTimeout(() => {
|
|
110
118
|
resolve({
|
|
111
119
|
subject: "acct:johndoe@example.com",
|
|
112
120
|
links: [
|
|
@@ -117,7 +125,7 @@ test("lookupObject()", {
|
|
|
117
125
|
},
|
|
118
126
|
],
|
|
119
127
|
});
|
|
120
|
-
}, 1000);
|
|
128
|
+
}, 1000));
|
|
121
129
|
}),
|
|
122
130
|
);
|
|
123
131
|
|
|
@@ -162,7 +170,7 @@ test("lookupObject()", {
|
|
|
162
170
|
"begin:https://example.com/.well-known/webfinger",
|
|
163
171
|
() =>
|
|
164
172
|
new Promise((resolve) => {
|
|
165
|
-
setTimeout(() => {
|
|
173
|
+
responseTimers.push(setTimeout(() => {
|
|
166
174
|
resolve({
|
|
167
175
|
subject: "acct:johndoe@example.com",
|
|
168
176
|
links: [
|
|
@@ -173,7 +181,7 @@ test("lookupObject()", {
|
|
|
173
181
|
},
|
|
174
182
|
],
|
|
175
183
|
});
|
|
176
|
-
}, 500);
|
|
184
|
+
}, 500));
|
|
177
185
|
}),
|
|
178
186
|
);
|
|
179
187
|
|
|
@@ -193,7 +201,7 @@ test("lookupObject()", {
|
|
|
193
201
|
"https://example.com/slow-object",
|
|
194
202
|
() =>
|
|
195
203
|
new Promise((resolve) => {
|
|
196
|
-
setTimeout(() => {
|
|
204
|
+
responseTimers.push(setTimeout(() => {
|
|
197
205
|
resolve({
|
|
198
206
|
status: 200,
|
|
199
207
|
headers: { "Content-Type": "application/activity+json" },
|
|
@@ -203,7 +211,7 @@ test("lookupObject()", {
|
|
|
203
211
|
content: "Slow response",
|
|
204
212
|
},
|
|
205
213
|
});
|
|
206
|
-
}, 1000);
|
|
214
|
+
}, 1000));
|
|
207
215
|
}),
|
|
208
216
|
);
|
|
209
217
|
|
|
@@ -218,6 +226,7 @@ test("lookupObject()", {
|
|
|
218
226
|
deepStrictEqual(await promise, null);
|
|
219
227
|
});
|
|
220
228
|
|
|
229
|
+
for (const timer of responseTimers) clearTimeout(timer);
|
|
221
230
|
fetchMock.hardReset();
|
|
222
231
|
fetchMock.removeRoutes();
|
|
223
232
|
});
|
|
@@ -601,6 +610,7 @@ test("FEP-fe34: lookupObject() cross-origin security", {
|
|
|
601
610
|
|
|
602
611
|
// Default behavior should return null
|
|
603
612
|
const result1 = await lookupObject("@user@example.com", {
|
|
613
|
+
...allowPrivateAddress,
|
|
604
614
|
documentLoader: webfingerDocumentLoader,
|
|
605
615
|
contextLoader: mockDocumentLoader,
|
|
606
616
|
});
|
|
@@ -610,6 +620,7 @@ test("FEP-fe34: lookupObject() cross-origin security", {
|
|
|
610
620
|
await rejects(
|
|
611
621
|
() =>
|
|
612
622
|
lookupObject("@user@example.com", {
|
|
623
|
+
...allowPrivateAddress,
|
|
613
624
|
documentLoader: webfingerDocumentLoader,
|
|
614
625
|
contextLoader: mockDocumentLoader,
|
|
615
626
|
crossOrigin: "throw",
|
|
@@ -620,6 +631,7 @@ test("FEP-fe34: lookupObject() cross-origin security", {
|
|
|
620
631
|
|
|
621
632
|
// With crossOrigin: trust, should return the object
|
|
622
633
|
const result2 = await lookupObject("@user@example.com", {
|
|
634
|
+
...allowPrivateAddress,
|
|
623
635
|
documentLoader: webfingerDocumentLoader,
|
|
624
636
|
contextLoader: mockDocumentLoader,
|
|
625
637
|
crossOrigin: "trust",
|
|
@@ -719,12 +731,22 @@ test("FEP-fe34: lookupObject() cross-origin security", {
|
|
|
719
731
|
throw new Error("Network error");
|
|
720
732
|
};
|
|
721
733
|
|
|
734
|
+
// The WebFinger fallback must not reach the network:
|
|
735
|
+
fetchMock.spyGlobal();
|
|
736
|
+
fetchMock.get("begin:https://example.com/.well-known/webfinger", 404);
|
|
737
|
+
|
|
722
738
|
// Network errors should not be confused with cross-origin errors
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
739
|
+
let result;
|
|
740
|
+
try {
|
|
741
|
+
result = await lookupObject("https://example.com/note", {
|
|
742
|
+
...allowPrivateAddress,
|
|
743
|
+
documentLoader: errorDocumentLoader,
|
|
744
|
+
contextLoader: mockDocumentLoader,
|
|
745
|
+
crossOrigin: "throw",
|
|
746
|
+
});
|
|
747
|
+
} finally {
|
|
748
|
+
fetchMock.hardReset();
|
|
749
|
+
}
|
|
728
750
|
|
|
729
751
|
// Should return null because the document loader failed,
|
|
730
752
|
// not because of cross-origin policy
|
|
@@ -842,6 +864,7 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
842
864
|
await t.step("records kind=actor for an actor result", async () => {
|
|
843
865
|
const [meterProvider, recorder] = createTestMeterProvider();
|
|
844
866
|
const person = await lookupObject("@johndoe@example.com", {
|
|
867
|
+
...allowPrivateAddress,
|
|
845
868
|
documentLoader: mockDocumentLoader,
|
|
846
869
|
contextLoader: mockDocumentLoader,
|
|
847
870
|
meterProvider,
|
|
@@ -928,6 +951,7 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
928
951
|
});
|
|
929
952
|
const [meterProvider, recorder] = createTestMeterProvider();
|
|
930
953
|
const result = await lookupObject("janedoe@example.com", {
|
|
954
|
+
...allowPrivateAddress,
|
|
931
955
|
documentLoader: mockDocumentLoader,
|
|
932
956
|
contextLoader: mockDocumentLoader,
|
|
933
957
|
meterProvider,
|
|
@@ -979,6 +1003,7 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
979
1003
|
);
|
|
980
1004
|
const [meterProvider, recorder] = createTestMeterProvider();
|
|
981
1005
|
await lookupObject("@johndoe@example.com", {
|
|
1006
|
+
...allowPrivateAddress,
|
|
982
1007
|
documentLoader: mockDocumentLoader,
|
|
983
1008
|
contextLoader: mockDocumentLoader,
|
|
984
1009
|
meterProvider,
|
|
@@ -1012,6 +1037,7 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
1012
1037
|
});
|
|
1013
1038
|
const [meterProvider, recorder] = createTestMeterProvider();
|
|
1014
1039
|
await lookupObject(new URL("acct:johndoe@example.com"), {
|
|
1040
|
+
...allowPrivateAddress,
|
|
1015
1041
|
documentLoader: mockDocumentLoader,
|
|
1016
1042
|
contextLoader: mockDocumentLoader,
|
|
1017
1043
|
meterProvider,
|
|
@@ -14,6 +14,9 @@ import { lookupObject } from "./lookup.ts";
|
|
|
14
14
|
import { assertInstanceOf } from "./utils.ts";
|
|
15
15
|
import { Person } from "./vocab.ts";
|
|
16
16
|
|
|
17
|
+
// Runtime-only transport override for hostname-based WebFinger mocks.
|
|
18
|
+
const allowPrivateAddress = { allowPrivateAddress: true };
|
|
19
|
+
|
|
17
20
|
const did = "did:key:z6Mkabc";
|
|
18
21
|
const actorId = `ap+ef61://${did}/actor`;
|
|
19
22
|
const gatewayPath = `/.well-known/apgateway/${did}/actor`;
|
|
@@ -92,6 +95,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
92
95
|
const actor = await lookupObject("@alice@example.com", {
|
|
93
96
|
documentLoader,
|
|
94
97
|
contextLoader: mockDocumentLoader,
|
|
98
|
+
...allowPrivateAddress,
|
|
95
99
|
verifyPortableObject,
|
|
96
100
|
});
|
|
97
101
|
assertInstanceOf(actor, Person);
|
|
@@ -118,6 +122,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
118
122
|
const actor = await lookupObject("@alice@example.com", {
|
|
119
123
|
documentLoader,
|
|
120
124
|
contextLoader: mockDocumentLoader,
|
|
125
|
+
...allowPrivateAddress,
|
|
121
126
|
verifyPortableObject: createVerifier(),
|
|
122
127
|
});
|
|
123
128
|
assertInstanceOf(actor, Person);
|
|
@@ -138,6 +143,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
138
143
|
const actor = await lookupObject("@alice@example.com", {
|
|
139
144
|
documentLoader,
|
|
140
145
|
contextLoader: mockDocumentLoader,
|
|
146
|
+
...allowPrivateAddress,
|
|
141
147
|
verifyPortableObject: createVerifier(),
|
|
142
148
|
gateways: ["https://second.example"],
|
|
143
149
|
});
|
|
@@ -153,6 +159,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
153
159
|
await lookupObject("@alice@example.com", {
|
|
154
160
|
documentLoader,
|
|
155
161
|
contextLoader: mockDocumentLoader,
|
|
162
|
+
...allowPrivateAddress,
|
|
156
163
|
verifyPortableObject: createVerifier(),
|
|
157
164
|
gateways: Array.from(
|
|
158
165
|
{ length: 6 },
|
|
@@ -178,6 +185,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
178
185
|
const actor = await lookupObject("@alice@example.com", {
|
|
179
186
|
documentLoader,
|
|
180
187
|
contextLoader: mockDocumentLoader,
|
|
188
|
+
...allowPrivateAddress,
|
|
181
189
|
verifyPortableObject: createVerifier(),
|
|
182
190
|
});
|
|
183
191
|
assertInstanceOf(actor, Person);
|
|
@@ -197,6 +205,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
197
205
|
const actor = await lookupObject("@alice@example.com", {
|
|
198
206
|
documentLoader,
|
|
199
207
|
contextLoader: mockDocumentLoader,
|
|
208
|
+
...allowPrivateAddress,
|
|
200
209
|
verifyPortableObject,
|
|
201
210
|
});
|
|
202
211
|
assertInstanceOf(actor, Person);
|
|
@@ -227,6 +236,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
227
236
|
await lookupObject("@alice@example.com", {
|
|
228
237
|
documentLoader,
|
|
229
238
|
contextLoader: mockDocumentLoader,
|
|
239
|
+
...allowPrivateAddress,
|
|
230
240
|
verifyPortableObject,
|
|
231
241
|
}),
|
|
232
242
|
null,
|
|
@@ -239,6 +249,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
239
249
|
lookupObject("@alice@example.com", {
|
|
240
250
|
documentLoader,
|
|
241
251
|
contextLoader: mockDocumentLoader,
|
|
252
|
+
...allowPrivateAddress,
|
|
242
253
|
verifyPortableObject,
|
|
243
254
|
crossOrigin: "throw",
|
|
244
255
|
}),
|
|
@@ -248,6 +259,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
248
259
|
await lookupObject("@alice@example.com", {
|
|
249
260
|
documentLoader,
|
|
250
261
|
contextLoader: mockDocumentLoader,
|
|
262
|
+
...allowPrivateAddress,
|
|
251
263
|
verifyPortableObject,
|
|
252
264
|
crossOrigin: "trust",
|
|
253
265
|
}),
|
|
@@ -270,6 +282,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
270
282
|
await lookupObject("@alice@example.com", {
|
|
271
283
|
documentLoader,
|
|
272
284
|
contextLoader: mockDocumentLoader,
|
|
285
|
+
...allowPrivateAddress,
|
|
273
286
|
crossOrigin,
|
|
274
287
|
}),
|
|
275
288
|
null,
|
|
@@ -281,6 +294,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
281
294
|
lookupObject("@alice@example.com", {
|
|
282
295
|
documentLoader,
|
|
283
296
|
contextLoader: mockDocumentLoader,
|
|
297
|
+
...allowPrivateAddress,
|
|
284
298
|
crossOrigin: "throw",
|
|
285
299
|
}),
|
|
286
300
|
/has a different origin than the document URL/,
|
|
@@ -292,6 +306,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
292
306
|
const actor = await lookupObject("@alice@example.com", {
|
|
293
307
|
documentLoader: httpLoader,
|
|
294
308
|
contextLoader: mockDocumentLoader,
|
|
309
|
+
...allowPrivateAddress,
|
|
295
310
|
});
|
|
296
311
|
assertInstanceOf(actor, Person);
|
|
297
312
|
deepStrictEqual(actor.id, new URL(compatibleId));
|
|
@@ -303,6 +318,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
303
318
|
const ordinary = await lookupObject(malformed, {
|
|
304
319
|
documentLoader: ordinaryLoader,
|
|
305
320
|
contextLoader: mockDocumentLoader,
|
|
321
|
+
...allowPrivateAddress,
|
|
306
322
|
});
|
|
307
323
|
assertInstanceOf(ordinary, Person);
|
|
308
324
|
deepStrictEqual(ordinaryLoader.fetched, [malformed]);
|
|
@@ -321,6 +337,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
321
337
|
const options = {
|
|
322
338
|
documentLoader,
|
|
323
339
|
contextLoader: mockDocumentLoader,
|
|
340
|
+
...allowPrivateAddress,
|
|
324
341
|
verifyPortableObject: createVerifier(),
|
|
325
342
|
};
|
|
326
343
|
equal(await lookupObject("@alice@example.com", options), null);
|
|
@@ -341,6 +358,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
341
358
|
const options = {
|
|
342
359
|
documentLoader,
|
|
343
360
|
contextLoader: mockDocumentLoader,
|
|
361
|
+
...allowPrivateAddress,
|
|
344
362
|
verifyPortableObject: createVerifier(),
|
|
345
363
|
};
|
|
346
364
|
equal(await lookupObject(dotted, options), null);
|
|
@@ -368,6 +386,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
368
386
|
await lookupObject("@alice@example.com", {
|
|
369
387
|
documentLoader,
|
|
370
388
|
contextLoader: mockDocumentLoader,
|
|
389
|
+
...allowPrivateAddress,
|
|
371
390
|
verifyPortableObject: createVerifier(),
|
|
372
391
|
}),
|
|
373
392
|
null,
|
|
@@ -397,6 +416,7 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
397
416
|
await lookupObject("@alice@example.com", {
|
|
398
417
|
documentLoader,
|
|
399
418
|
contextLoader: mockDocumentLoader,
|
|
419
|
+
...allowPrivateAddress,
|
|
400
420
|
verifyPortableObject,
|
|
401
421
|
signal: controller.signal,
|
|
402
422
|
}),
|
|
@@ -573,13 +593,25 @@ test("getActorHandle() with FEP-ef61 portable actors", {
|
|
|
573
593
|
"https://example.com/.well-known/webfinger?resource=acct%3Aalice%40example.com",
|
|
574
594
|
selfLinks(compatibleId),
|
|
575
595
|
);
|
|
576
|
-
deepStrictEqual(
|
|
596
|
+
deepStrictEqual(
|
|
597
|
+
await getActorHandle(actor, {
|
|
598
|
+
...allowPrivateAddress,
|
|
599
|
+
userAgent: undefined,
|
|
600
|
+
}),
|
|
601
|
+
"@alice@example.com",
|
|
602
|
+
);
|
|
577
603
|
});
|
|
578
604
|
|
|
579
605
|
await t.step("canonical self link", async () => {
|
|
580
606
|
fetchMock.removeRoutes();
|
|
581
607
|
fetchMock.get(webFingerPrefix, selfLinks(`ap://${did}/actor`));
|
|
582
|
-
deepStrictEqual(
|
|
608
|
+
deepStrictEqual(
|
|
609
|
+
await getActorHandle(actor, {
|
|
610
|
+
...allowPrivateAddress,
|
|
611
|
+
userAgent: undefined,
|
|
612
|
+
}),
|
|
613
|
+
"@alice@example.com",
|
|
614
|
+
);
|
|
583
615
|
});
|
|
584
616
|
|
|
585
617
|
await t.step("follows a verified subject", async () => {
|
|
@@ -592,7 +624,13 @@ test("getActorHandle() with FEP-ef61 portable actors", {
|
|
|
592
624
|
"begin:https://example.org/.well-known/webfinger",
|
|
593
625
|
{ ...selfLinks(compatibleId), subject: "acct:alice@example.org" },
|
|
594
626
|
);
|
|
595
|
-
deepStrictEqual(
|
|
627
|
+
deepStrictEqual(
|
|
628
|
+
await getActorHandle(actor, {
|
|
629
|
+
...allowPrivateAddress,
|
|
630
|
+
userAgent: undefined,
|
|
631
|
+
}),
|
|
632
|
+
"@alice@example.org",
|
|
633
|
+
);
|
|
596
634
|
|
|
597
635
|
// An unverified subject is ignored:
|
|
598
636
|
fetchMock.removeRoutes();
|
|
@@ -604,7 +642,13 @@ test("getActorHandle() with FEP-ef61 portable actors", {
|
|
|
604
642
|
"begin:https://example.org/.well-known/webfinger",
|
|
605
643
|
selfLinks(`ap://${did}/other`),
|
|
606
644
|
);
|
|
607
|
-
deepStrictEqual(
|
|
645
|
+
deepStrictEqual(
|
|
646
|
+
await getActorHandle(actor, {
|
|
647
|
+
...allowPrivateAddress,
|
|
648
|
+
userAgent: undefined,
|
|
649
|
+
}),
|
|
650
|
+
"@alice@example.com",
|
|
651
|
+
);
|
|
608
652
|
});
|
|
609
653
|
|
|
610
654
|
await t.step("rejects a WebFinger response for another actor", async () => {
|
|
@@ -617,14 +661,28 @@ test("getActorHandle() with FEP-ef61 portable actors", {
|
|
|
617
661
|
) {
|
|
618
662
|
fetchMock.removeRoutes();
|
|
619
663
|
fetchMock.get(webFingerPrefix, jrd);
|
|
620
|
-
await rejects(
|
|
664
|
+
await rejects(
|
|
665
|
+
() =>
|
|
666
|
+
getActorHandle(actor, {
|
|
667
|
+
...allowPrivateAddress,
|
|
668
|
+
userAgent: undefined,
|
|
669
|
+
}),
|
|
670
|
+
TypeError,
|
|
671
|
+
);
|
|
621
672
|
}
|
|
622
673
|
});
|
|
623
674
|
|
|
624
675
|
await t.step("does not fall back when WebFinger fails", async () => {
|
|
625
676
|
fetchMock.removeRoutes();
|
|
626
677
|
fetchMock.get(webFingerPrefix, 404);
|
|
627
|
-
await rejects(
|
|
678
|
+
await rejects(
|
|
679
|
+
() =>
|
|
680
|
+
getActorHandle(actor, {
|
|
681
|
+
...allowPrivateAddress,
|
|
682
|
+
userAgent: undefined,
|
|
683
|
+
}),
|
|
684
|
+
TypeError,
|
|
685
|
+
);
|
|
628
686
|
});
|
|
629
687
|
|
|
630
688
|
await t.step("not enough information", async () => {
|
|
@@ -640,7 +698,14 @@ test("getActorHandle() with FEP-ef61 portable actors", {
|
|
|
640
698
|
}),
|
|
641
699
|
]
|
|
642
700
|
) {
|
|
643
|
-
await rejects(
|
|
701
|
+
await rejects(
|
|
702
|
+
() =>
|
|
703
|
+
getActorHandle(target, {
|
|
704
|
+
...allowPrivateAddress,
|
|
705
|
+
userAgent: undefined,
|
|
706
|
+
}),
|
|
707
|
+
TypeError,
|
|
708
|
+
);
|
|
644
709
|
}
|
|
645
710
|
deepStrictEqual(fetchMock.callHistory.calls().length, 0);
|
|
646
711
|
});
|
package/src/vocab.test.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createDocumentLoader } from "../../vocab-runtime/src/docloader.ts";
|
|
2
|
+
import { createPublicFetch } from "../../vocab-runtime/src/public-fetch.ts";
|
|
1
3
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
2
4
|
import {
|
|
3
5
|
decodeMultibase,
|
|
@@ -1996,7 +1998,14 @@ test({
|
|
|
1996
1998
|
const activity2 = new Activity({
|
|
1997
1999
|
object: new URL("https://example.com/not-found"),
|
|
1998
2000
|
});
|
|
1999
|
-
deepStrictEqual(
|
|
2001
|
+
deepStrictEqual(
|
|
2002
|
+
await activity2.getObject({
|
|
2003
|
+
documentLoader: mockDocumentLoader,
|
|
2004
|
+
contextLoader: mockDocumentLoader,
|
|
2005
|
+
suppressError: true,
|
|
2006
|
+
}),
|
|
2007
|
+
null,
|
|
2008
|
+
);
|
|
2000
2009
|
|
|
2001
2010
|
const activity3 = await Activity.fromJsonLd({
|
|
2002
2011
|
"@context": "https://www.w3.org/ns/activitystreams",
|
|
@@ -2208,7 +2217,11 @@ test({
|
|
|
2208
2217
|
],
|
|
2209
2218
|
});
|
|
2210
2219
|
const objects2 = await Array.fromAsync(
|
|
2211
|
-
activity2.getObjects({
|
|
2220
|
+
activity2.getObjects({
|
|
2221
|
+
documentLoader: mockDocumentLoader,
|
|
2222
|
+
contextLoader: mockDocumentLoader,
|
|
2223
|
+
suppressError: true,
|
|
2224
|
+
}),
|
|
2212
2225
|
);
|
|
2213
2226
|
deepStrictEqual(objects2.length, 1);
|
|
2214
2227
|
assertInstanceOf(objects2[0], Object);
|
|
@@ -6347,6 +6360,15 @@ for (const typeUri in types) {
|
|
|
6347
6360
|
}
|
|
6348
6361
|
|
|
6349
6362
|
test("Announce.getObject() suppresses redirect, context, and private URL logs", async () => {
|
|
6363
|
+
// Validate every hop, including private redirect targets, while keeping
|
|
6364
|
+
// hostname-based fetch mocks independent of runtime connection pinning.
|
|
6365
|
+
const publicFetch = createPublicFetch({
|
|
6366
|
+
pinner: () => Promise.resolve(null),
|
|
6367
|
+
lookup: () => Promise.resolve([{ address: "93.184.215.14", family: 4 }]),
|
|
6368
|
+
});
|
|
6369
|
+
const documentLoader = createDocumentLoader({}, {
|
|
6370
|
+
openHop: (url) => publicFetch.openPublicFetch(url),
|
|
6371
|
+
});
|
|
6350
6372
|
const records: LogRecord[] = [];
|
|
6351
6373
|
const objectUrl = "https://example.com/suppression-object";
|
|
6352
6374
|
const contextUrl = "https://example.com/suppression-context";
|
|
@@ -6408,7 +6430,14 @@ test("Announce.getObject() suppresses redirect, context, and private URL logs",
|
|
|
6408
6430
|
),
|
|
6409
6431
|
});
|
|
6410
6432
|
if (suppressError) {
|
|
6411
|
-
deepStrictEqual(
|
|
6433
|
+
deepStrictEqual(
|
|
6434
|
+
await announce.getObject({
|
|
6435
|
+
suppressError,
|
|
6436
|
+
documentLoader,
|
|
6437
|
+
contextLoader: documentLoader,
|
|
6438
|
+
}),
|
|
6439
|
+
null,
|
|
6440
|
+
);
|
|
6412
6441
|
deepStrictEqual(
|
|
6413
6442
|
records.filter((r) => r.level === "error"),
|
|
6414
6443
|
[],
|
|
@@ -6416,7 +6445,13 @@ test("Announce.getObject() suppresses redirect, context, and private URL logs",
|
|
|
6416
6445
|
);
|
|
6417
6446
|
ok(records.some((r) => r.level === "warning"), scenario);
|
|
6418
6447
|
} else {
|
|
6419
|
-
await rejects(() =>
|
|
6448
|
+
await rejects(() =>
|
|
6449
|
+
announce.getObject({
|
|
6450
|
+
suppressError,
|
|
6451
|
+
documentLoader,
|
|
6452
|
+
contextLoader: documentLoader,
|
|
6453
|
+
})
|
|
6454
|
+
);
|
|
6420
6455
|
ok(records.some((r) => r.level === "error"), scenario);
|
|
6421
6456
|
}
|
|
6422
6457
|
if (scenario === "private") deepStrictEqual(fetches, 0);
|
|
@@ -6655,7 +6690,7 @@ test("portable verifiers suppress document logs only during dereferencing", asyn
|
|
|
6655
6690
|
try {
|
|
6656
6691
|
for (const suppressError of [true, false, undefined]) {
|
|
6657
6692
|
records.length = 0;
|
|
6658
|
-
const baseLoader = getDocumentLoader();
|
|
6693
|
+
const baseLoader = getDocumentLoader({ allowPrivateAddress: true });
|
|
6659
6694
|
const calls: Parameters<DocumentLoader>[1][] = [];
|
|
6660
6695
|
const documentLoader: DocumentLoader = (url, options) => {
|
|
6661
6696
|
calls.push(options);
|