@fedify/vocab 2.4.0-dev.2077 → 2.4.0-dev.2093
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 +1 -1
- package/dist/mod.js +1 -1
- package/dist-tests/{actor-BvcvJ4UX.mjs → actor-BqI2hrlv.mjs} +1 -1
- package/dist-tests/actor.test.mjs +1 -1
- package/dist-tests/gateway.test.mjs +19 -10
- package/dist-tests/{lookup-K74BlMOT.mjs → lookup-bESEuLBl.mjs} +1 -1
- package/dist-tests/lookup.test.mjs +1 -1
- package/dist-tests/portable-lookup.test.mjs +30 -6
- package/dist-tests/translation.test.mjs +2 -2
- package/package.json +4 -4
- package/src/gateway.test.ts +25 -10
- package/src/portable-lookup.test.ts +38 -5
package/deno.json
CHANGED
package/dist/mod.cjs
CHANGED
|
@@ -36,7 +36,7 @@ let _fedify_vocab_runtime_temporal = require("@fedify/vocab-runtime/temporal");
|
|
|
36
36
|
let es_toolkit = require("es-toolkit");
|
|
37
37
|
//#region deno.json
|
|
38
38
|
var name = "@fedify/vocab";
|
|
39
|
-
var version = "2.4.0-dev.
|
|
39
|
+
var version = "2.4.0-dev.2093+e9706a54";
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/type.ts
|
|
42
42
|
function getTypeId(object) {
|
package/dist/mod.js
CHANGED
|
@@ -12,7 +12,7 @@ import { isTemporalDuration, isTemporalInstant } from "@fedify/vocab-runtime/tem
|
|
|
12
12
|
import { delay } from "es-toolkit";
|
|
13
13
|
//#region deno.json
|
|
14
14
|
var name = "@fedify/vocab";
|
|
15
|
-
var version = "2.4.0-dev.
|
|
15
|
+
var version = "2.4.0-dev.2093+e9706a54";
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/type.ts
|
|
18
18
|
function getTypeId(object) {
|
|
@@ -8,7 +8,7 @@ import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
|
8
8
|
import { domainToASCII, domainToUnicode } from "node:url";
|
|
9
9
|
//#region deno.json
|
|
10
10
|
var name = "@fedify/vocab";
|
|
11
|
-
var version = "2.4.0-dev.
|
|
11
|
+
var version = "2.4.0-dev.2093+e9706a54";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/actor.ts
|
|
14
14
|
const ACTOR_DISCOVERY_HISTOGRAM_BUCKETS = [
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { F as Person, P as Organization, Q as __exportAll, U as Service, a as Application, b as Group } from "./vocab-BHtBRusa.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-C9nxP5_e.mjs";
|
|
5
|
-
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-
|
|
5
|
+
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-BqI2hrlv.mjs";
|
|
6
6
|
import { createTestMeterProvider, test } from "@fedify/fixture";
|
|
7
7
|
import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert/strict";
|
|
8
8
|
//#region ../../node_modules/.pnpm/fast-check@3.23.2/node_modules/fast-check/lib/esm/check/precondition/PreconditionFailure.js
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { F as Person, M as OrderedCollection, c as CollectionPage, k as Note, s as Collection, u as Create } from "./vocab-BHtBRusa.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-C9nxP5_e.mjs";
|
|
5
|
-
import { n as traverseCollection } from "./lookup-
|
|
5
|
+
import { n as traverseCollection } from "./lookup-bESEuLBl.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
@@ -165,7 +165,8 @@ test("getObject() rejects objects with a mismatching portable ID", async (t) =>
|
|
|
165
165
|
"another path": `ap://${did}/objects/2`,
|
|
166
166
|
"a dot segment": `ap://${did}/objects/x/../1`,
|
|
167
167
|
"a fragment": `ap://${did}/objects/1#fragment`,
|
|
168
|
-
"a compatible identifier": `https://gw1.example
|
|
168
|
+
"a compatible identifier of another DID": `https://gw1.example/.well-known/apgateway/did:key:z6Mkdef/objects/1`,
|
|
169
|
+
"a compatible identifier of another path": `https://gw1.example/.well-known/apgateway/${did}/objects/2`,
|
|
169
170
|
"an HTTP(S) ID": "https://gw1.example/objects/1"
|
|
170
171
|
};
|
|
171
172
|
for (const [name, id] of globalThis.Object.entries(mismatches)) await t.step(name, async () => {
|
|
@@ -856,14 +857,14 @@ test("accessors reject forged objects at compatible identifiers", async () => {
|
|
|
856
857
|
"ignore",
|
|
857
858
|
"trust"
|
|
858
859
|
]) {
|
|
859
|
-
const verifier = createRecordingVerifier();
|
|
860
|
+
const verifier = createRecordingVerifier(() => ({ verified: false }));
|
|
860
861
|
deepStrictEqual(await (await createHttpActivity(forgedId)).getObject({
|
|
861
862
|
documentLoader: createLoader({ [forgedId]: forged }),
|
|
862
863
|
contextLoader: mockDocumentLoader,
|
|
863
864
|
verifyPortableObject: verifier,
|
|
864
865
|
crossOrigin
|
|
865
866
|
}), null);
|
|
866
|
-
deepStrictEqual(verifier.calls, []);
|
|
867
|
+
deepStrictEqual(verifier.calls.map((c) => c.document), [forged]);
|
|
867
868
|
deepStrictEqual(await (await createHttpActivity(forgedId)).getObject({
|
|
868
869
|
documentLoader: createLoader({ [forgedId]: note() }),
|
|
869
870
|
contextLoader: mockDocumentLoader,
|
|
@@ -923,7 +924,7 @@ test("accessors keep fetching compatible identifiers as HTTP(S) URLs without ver
|
|
|
923
924
|
deepStrictEqual(await activity.getObject({
|
|
924
925
|
documentLoader,
|
|
925
926
|
contextLoader: mockDocumentLoader,
|
|
926
|
-
verifyPortableObject: createVerifier()
|
|
927
|
+
verifyPortableObject: createVerifier(false)
|
|
927
928
|
}), null);
|
|
928
929
|
deepStrictEqual(documentLoader.fetched, [compatibleNoteId, compatibleNoteId]);
|
|
929
930
|
});
|
|
@@ -937,7 +938,7 @@ test("accessors keep fetching compatible identifiers as HTTP(S) URLs without ver
|
|
|
937
938
|
deepStrictEqual(await Array.fromAsync(activity.getObjects({
|
|
938
939
|
documentLoader,
|
|
939
940
|
contextLoader: mockDocumentLoader,
|
|
940
|
-
verifyPortableObject: createVerifier()
|
|
941
|
+
verifyPortableObject: createVerifier(false)
|
|
941
942
|
})), []);
|
|
942
943
|
});
|
|
943
944
|
await t.step("redirects to ordinary objects", async () => {
|
|
@@ -1066,7 +1067,7 @@ test("accessors verify fetched documents that stand for portable objects", async
|
|
|
1066
1067
|
await t.step("a document that claims another object", async () => {
|
|
1067
1068
|
for (const id of [
|
|
1068
1069
|
`ap://${did}/objects/2`,
|
|
1069
|
-
|
|
1070
|
+
gatewayUrl("https://gw.example", "/objects/2"),
|
|
1070
1071
|
"https://gw.example/notes/1"
|
|
1071
1072
|
]) {
|
|
1072
1073
|
const verifier = createRecordingVerifier();
|
|
@@ -1101,12 +1102,20 @@ test("accessors verify fetched documents that stand for portable objects", async
|
|
|
1101
1102
|
await t.step("a compatible @id", async () => {
|
|
1102
1103
|
const verifier = createRecordingVerifier();
|
|
1103
1104
|
const url = "https://gw.example/notes/1";
|
|
1104
|
-
|
|
1105
|
-
|
|
1105
|
+
const documentLoader = createLoader({ [url]: note(compatibleNoteId) });
|
|
1106
|
+
const object = await (await createHttpActivity(url)).getObject({
|
|
1107
|
+
documentLoader,
|
|
1106
1108
|
contextLoader: mockDocumentLoader,
|
|
1107
1109
|
verifyPortableObject: verifier
|
|
1110
|
+
});
|
|
1111
|
+
assertInstanceOf(object, Note);
|
|
1112
|
+
deepStrictEqual(object.id, new URL(compatibleNoteId));
|
|
1113
|
+
deepStrictEqual(verifier.calls.length, 1);
|
|
1114
|
+
deepStrictEqual(await (await createHttpActivity(url)).getObject({
|
|
1115
|
+
documentLoader,
|
|
1116
|
+
contextLoader: mockDocumentLoader,
|
|
1117
|
+
verifyPortableObject: createVerifier(false)
|
|
1108
1118
|
}), null);
|
|
1109
|
-
deepStrictEqual(verifier.calls, []);
|
|
1110
1119
|
});
|
|
1111
1120
|
await t.step("a portable final URL", async () => {
|
|
1112
1121
|
for (const [id, expected] of [[objectId, true], [`ap://${did}/objects/2`, false]]) deepStrictEqual(await (await createHttpActivity(plainUrl)).getObject({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1 } from "./vocab-BHtBRusa.mjs";
|
|
4
|
-
import { i as isActor, o as name, s as version } from "./actor-
|
|
4
|
+
import { i as isActor, o as name, s as version } from "./actor-BqI2hrlv.mjs";
|
|
5
5
|
import { t as getTypeId } from "./type-BMdjm4Eg.mjs";
|
|
6
6
|
import { canonicalizePortableUri, formatIri, getDocumentLoader, haveSameFe34Origin, haveSameIriOrigin, parseIri } from "@fedify/vocab-runtime";
|
|
7
7
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1, F as Person, k as Note, s as Collection } from "./vocab-BHtBRusa.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-C9nxP5_e.mjs";
|
|
5
|
-
import { n as traverseCollection, t as lookupObject } from "./lookup-
|
|
5
|
+
import { n as traverseCollection, t as lookupObject } from "./lookup-bESEuLBl.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict";
|
|
@@ -2,8 +2,8 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { F as Person } from "./vocab-BHtBRusa.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-C9nxP5_e.mjs";
|
|
5
|
-
import { n as getActorHandle } from "./actor-
|
|
6
|
-
import { t as lookupObject } from "./lookup-
|
|
5
|
+
import { n as getActorHandle } from "./actor-BqI2hrlv.mjs";
|
|
6
|
+
import { t as lookupObject } from "./lookup-bESEuLBl.mjs";
|
|
7
7
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
8
8
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
9
9
|
import { deepStrictEqual, equal, rejects } from "node:assert/strict";
|
|
@@ -110,13 +110,29 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
110
110
|
}), Person);
|
|
111
111
|
deepStrictEqual(documentLoader.fetched, [compatibleId, other]);
|
|
112
112
|
});
|
|
113
|
+
await t.step("accepts a compatible identifier as the ID", async () => {
|
|
114
|
+
esm_default.removeRoutes();
|
|
115
|
+
esm_default.get(webFingerPrefix, selfLinks(compatibleId));
|
|
116
|
+
const document = person(compatibleId);
|
|
117
|
+
const documentLoader = createLoader({ [compatibleId]: document });
|
|
118
|
+
const verifyPortableObject = createVerifier();
|
|
119
|
+
const actor = await lookupObject("@alice@example.com", {
|
|
120
|
+
documentLoader,
|
|
121
|
+
contextLoader: mockDocumentLoader,
|
|
122
|
+
verifyPortableObject
|
|
123
|
+
});
|
|
124
|
+
assertInstanceOf(actor, Person);
|
|
125
|
+
deepStrictEqual(actor.id, new URL(compatibleId));
|
|
126
|
+
deepStrictEqual(verifyPortableObject.documents, [document]);
|
|
127
|
+
});
|
|
113
128
|
await t.step("rejects objects that fail the checks", async () => {
|
|
114
129
|
esm_default.removeRoutes();
|
|
115
130
|
esm_default.get(webFingerPrefix, selfLinks(compatibleId));
|
|
116
131
|
for (const [document, verified] of [
|
|
117
132
|
[person(), false],
|
|
118
133
|
[person(`ap://${did}/other`), true],
|
|
119
|
-
[person(
|
|
134
|
+
[person(`https://example.com/.well-known/apgateway/${did}/other`), true],
|
|
135
|
+
[person(compatibleId), false]
|
|
120
136
|
]) {
|
|
121
137
|
const documentLoader = createLoader({ [compatibleId]: document });
|
|
122
138
|
const verifyPortableObject = createVerifier(verified);
|
|
@@ -390,14 +406,22 @@ test("lookupObject() verifies fetched documents that stand for portable objects"
|
|
|
390
406
|
}), null);
|
|
391
407
|
});
|
|
392
408
|
await t.step("a compatible @id", async () => {
|
|
393
|
-
const
|
|
409
|
+
const document = person(compatibleId);
|
|
410
|
+
const documentLoader = redirectingLoader(plainUrl, document);
|
|
394
411
|
const verifyPortableObject = createVerifier();
|
|
395
|
-
|
|
412
|
+
const verified = await lookupObject(plainUrl, {
|
|
396
413
|
documentLoader,
|
|
397
414
|
contextLoader: mockDocumentLoader,
|
|
398
415
|
verifyPortableObject
|
|
416
|
+
});
|
|
417
|
+
assertInstanceOf(verified, Person);
|
|
418
|
+
deepStrictEqual(verified.id, new URL(compatibleId));
|
|
419
|
+
deepStrictEqual(verifyPortableObject.documents, [document]);
|
|
420
|
+
equal(await lookupObject(plainUrl, {
|
|
421
|
+
documentLoader,
|
|
422
|
+
contextLoader: mockDocumentLoader,
|
|
423
|
+
verifyPortableObject: createVerifier(false)
|
|
399
424
|
}), null);
|
|
400
|
-
deepStrictEqual(verifyPortableObject.documents, []);
|
|
401
425
|
const actor = await lookupObject(plainUrl, {
|
|
402
426
|
documentLoader,
|
|
403
427
|
contextLoader: mockDocumentLoader
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1, E as Link, F as Person, K as Translation, L as PropertyValue, P as Organization, U as Service, a as Application, b as Group, k as Note, o as Article, q as Update, s as Collection, u as Create } from "./vocab-BHtBRusa.mjs";
|
|
4
|
-
import "./actor-
|
|
5
|
-
import "./lookup-
|
|
4
|
+
import "./actor-BqI2hrlv.mjs";
|
|
5
|
+
import "./lookup-bESEuLBl.mjs";
|
|
6
6
|
import { test } from "@fedify/fixture";
|
|
7
7
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
8
8
|
import { LanguageString as LanguageString$1, getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.2093+e9706a54",
|
|
4
4
|
"homepage": "https://fedify.dev/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"jsonld": "^9.0.0",
|
|
44
44
|
"pkijs": "^3.3.3",
|
|
45
45
|
"temporal-polyfill": "^1.0.1",
|
|
46
|
-
"@fedify/
|
|
47
|
-
"@fedify/
|
|
48
|
-
"@fedify/vocab-runtime": "2.4.0-dev.
|
|
46
|
+
"@fedify/webfinger": "2.4.0-dev.2093+e9706a54",
|
|
47
|
+
"@fedify/vocab-tools": "2.4.0-dev.2093+e9706a54",
|
|
48
|
+
"@fedify/vocab-runtime": "2.4.0-dev.2093+e9706a54"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.12.2",
|
package/src/gateway.test.ts
CHANGED
|
@@ -262,7 +262,10 @@ test("getObject() rejects objects with a mismatching portable ID", async (t) =>
|
|
|
262
262
|
"another path": `ap://${did}/objects/2`,
|
|
263
263
|
"a dot segment": `ap://${did}/objects/x/../1`,
|
|
264
264
|
"a fragment": `ap://${did}/objects/1#fragment`,
|
|
265
|
-
"a compatible identifier":
|
|
265
|
+
"a compatible identifier of another DID":
|
|
266
|
+
`https://gw1.example/.well-known/apgateway/did:key:z6Mkdef/objects/1`,
|
|
267
|
+
"a compatible identifier of another path":
|
|
268
|
+
`https://gw1.example/.well-known/apgateway/${did}/objects/2`,
|
|
266
269
|
"an HTTP(S) ID": "https://gw1.example/objects/1",
|
|
267
270
|
};
|
|
268
271
|
for (const [name, id] of globalThis.Object.entries(mismatches)) {
|
|
@@ -1239,8 +1242,10 @@ test("accessors reject forged objects at compatible identifiers", async () => {
|
|
|
1239
1242
|
content: "Forged",
|
|
1240
1243
|
};
|
|
1241
1244
|
for (const crossOrigin of [undefined, "ignore", "trust"] as const) {
|
|
1242
|
-
// Its @id
|
|
1243
|
-
|
|
1245
|
+
// Its @id, the compatible identifier itself, stands for the requested
|
|
1246
|
+
// portable object, so the proof policy decides, which rejects it for
|
|
1247
|
+
// lacking a proof:
|
|
1248
|
+
const verifier = createRecordingVerifier(() => ({ verified: false }));
|
|
1244
1249
|
deepStrictEqual(
|
|
1245
1250
|
await (await createHttpActivity(forgedId)).getObject({
|
|
1246
1251
|
documentLoader: createLoader({ [forgedId]: forged }),
|
|
@@ -1250,7 +1255,7 @@ test("accessors reject forged objects at compatible identifiers", async () => {
|
|
|
1250
1255
|
}),
|
|
1251
1256
|
null,
|
|
1252
1257
|
);
|
|
1253
|
-
deepStrictEqual(verifier.calls, []);
|
|
1258
|
+
deepStrictEqual(verifier.calls.map((c) => c.document), [forged]);
|
|
1254
1259
|
// With a portable ID, it fails the proof policy:
|
|
1255
1260
|
deepStrictEqual(
|
|
1256
1261
|
await (await createHttpActivity(forgedId)).getObject({
|
|
@@ -1335,7 +1340,7 @@ test("accessors keep fetching compatible identifiers as HTTP(S) URLs without ver
|
|
|
1335
1340
|
await activity.getObject({
|
|
1336
1341
|
documentLoader,
|
|
1337
1342
|
contextLoader: mockDocumentLoader,
|
|
1338
|
-
verifyPortableObject: createVerifier(),
|
|
1343
|
+
verifyPortableObject: createVerifier(false),
|
|
1339
1344
|
}),
|
|
1340
1345
|
null,
|
|
1341
1346
|
);
|
|
@@ -1357,7 +1362,7 @@ test("accessors keep fetching compatible identifiers as HTTP(S) URLs without ver
|
|
|
1357
1362
|
await Array.fromAsync(activity.getObjects({
|
|
1358
1363
|
documentLoader,
|
|
1359
1364
|
contextLoader: mockDocumentLoader,
|
|
1360
|
-
verifyPortableObject: createVerifier(),
|
|
1365
|
+
verifyPortableObject: createVerifier(false),
|
|
1361
1366
|
})),
|
|
1362
1367
|
[],
|
|
1363
1368
|
);
|
|
@@ -1540,7 +1545,7 @@ test("accessors verify fetched documents that stand for portable objects", async
|
|
|
1540
1545
|
for (
|
|
1541
1546
|
const id of [
|
|
1542
1547
|
`ap://${did}/objects/2`,
|
|
1543
|
-
|
|
1548
|
+
gatewayUrl("https://gw.example", "/objects/2"),
|
|
1544
1549
|
"https://gw.example/notes/1",
|
|
1545
1550
|
]
|
|
1546
1551
|
) {
|
|
@@ -1583,17 +1588,27 @@ test("accessors verify fetched documents that stand for portable objects", async
|
|
|
1583
1588
|
});
|
|
1584
1589
|
|
|
1585
1590
|
await t.step("a compatible @id", async () => {
|
|
1591
|
+
// The compatible identifier stands for the portable object, so the
|
|
1592
|
+
// document is verified as that object, keeping its own @id:
|
|
1586
1593
|
const verifier = createRecordingVerifier();
|
|
1587
1594
|
const url = "https://gw.example/notes/1";
|
|
1595
|
+
const documentLoader = createLoader({ [url]: note(compatibleNoteId) });
|
|
1596
|
+
const object = await (await createHttpActivity(url)).getObject({
|
|
1597
|
+
documentLoader,
|
|
1598
|
+
contextLoader: mockDocumentLoader,
|
|
1599
|
+
verifyPortableObject: verifier,
|
|
1600
|
+
});
|
|
1601
|
+
assertInstanceOf(object, Note);
|
|
1602
|
+
deepStrictEqual(object.id, new URL(compatibleNoteId));
|
|
1603
|
+
deepStrictEqual(verifier.calls.length, 1);
|
|
1588
1604
|
deepStrictEqual(
|
|
1589
1605
|
await (await createHttpActivity(url)).getObject({
|
|
1590
|
-
documentLoader
|
|
1606
|
+
documentLoader,
|
|
1591
1607
|
contextLoader: mockDocumentLoader,
|
|
1592
|
-
verifyPortableObject:
|
|
1608
|
+
verifyPortableObject: createVerifier(false),
|
|
1593
1609
|
}),
|
|
1594
1610
|
null,
|
|
1595
1611
|
);
|
|
1596
|
-
deepStrictEqual(verifier.calls, []);
|
|
1597
1612
|
});
|
|
1598
1613
|
|
|
1599
1614
|
await t.step("a portable final URL", async () => {
|
|
@@ -143,6 +143,25 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
143
143
|
deepStrictEqual(documentLoader.fetched, [compatibleId, other]);
|
|
144
144
|
});
|
|
145
145
|
|
|
146
|
+
await t.step("accepts a compatible identifier as the ID", async () => {
|
|
147
|
+
// Some publishers, e.g., tootik, identify their portable actors by
|
|
148
|
+
// compatible identifiers; the document is verified as the portable
|
|
149
|
+
// object, and keeps its own ID:
|
|
150
|
+
fetchMock.removeRoutes();
|
|
151
|
+
fetchMock.get(webFingerPrefix, selfLinks(compatibleId));
|
|
152
|
+
const document = person(compatibleId);
|
|
153
|
+
const documentLoader = createLoader({ [compatibleId]: document });
|
|
154
|
+
const verifyPortableObject = createVerifier();
|
|
155
|
+
const actor = await lookupObject("@alice@example.com", {
|
|
156
|
+
documentLoader,
|
|
157
|
+
contextLoader: mockDocumentLoader,
|
|
158
|
+
verifyPortableObject,
|
|
159
|
+
});
|
|
160
|
+
assertInstanceOf(actor, Person);
|
|
161
|
+
deepStrictEqual(actor.id, new URL(compatibleId));
|
|
162
|
+
deepStrictEqual(verifyPortableObject.documents, [document]);
|
|
163
|
+
});
|
|
164
|
+
|
|
146
165
|
await t.step("rejects objects that fail the checks", async () => {
|
|
147
166
|
fetchMock.removeRoutes();
|
|
148
167
|
fetchMock.get(webFingerPrefix, selfLinks(compatibleId));
|
|
@@ -151,8 +170,13 @@ test("lookupObject() with FEP-ef61 portable actors", {
|
|
|
151
170
|
[person(), false],
|
|
152
171
|
// Same DID, but another object:
|
|
153
172
|
[person(`ap://${did}/other`), true],
|
|
154
|
-
// A compatible identifier
|
|
155
|
-
[
|
|
173
|
+
// A compatible identifier of another object:
|
|
174
|
+
[
|
|
175
|
+
person(`https://example.com/.well-known/apgateway/${did}/other`),
|
|
176
|
+
true,
|
|
177
|
+
],
|
|
178
|
+
// A compatible identifier of the object, but unverified:
|
|
179
|
+
[person(compatibleId), false],
|
|
156
180
|
] as const
|
|
157
181
|
) {
|
|
158
182
|
const documentLoader = createLoader({ [compatibleId]: document });
|
|
@@ -539,17 +563,26 @@ test("lookupObject() verifies fetched documents that stand for portable objects"
|
|
|
539
563
|
});
|
|
540
564
|
|
|
541
565
|
await t.step("a compatible @id", async () => {
|
|
542
|
-
const
|
|
566
|
+
const document = person(compatibleId);
|
|
567
|
+
const documentLoader = redirectingLoader(plainUrl, document);
|
|
568
|
+
// The document stands for the portable object, and is verified as it:
|
|
543
569
|
const verifyPortableObject = createVerifier();
|
|
570
|
+
const verified = await lookupObject(plainUrl, {
|
|
571
|
+
documentLoader,
|
|
572
|
+
contextLoader: mockDocumentLoader,
|
|
573
|
+
verifyPortableObject,
|
|
574
|
+
});
|
|
575
|
+
assertInstanceOf(verified, Person);
|
|
576
|
+
deepStrictEqual(verified.id, new URL(compatibleId));
|
|
577
|
+
deepStrictEqual(verifyPortableObject.documents, [document]);
|
|
544
578
|
equal(
|
|
545
579
|
await lookupObject(plainUrl, {
|
|
546
580
|
documentLoader,
|
|
547
581
|
contextLoader: mockDocumentLoader,
|
|
548
|
-
verifyPortableObject,
|
|
582
|
+
verifyPortableObject: createVerifier(false),
|
|
549
583
|
}),
|
|
550
584
|
null,
|
|
551
585
|
);
|
|
552
|
-
deepStrictEqual(verifyPortableObject.documents, []);
|
|
553
586
|
// Without verifyPortableObject, it is fetched as before:
|
|
554
587
|
const actor = await lookupObject(plainUrl, {
|
|
555
588
|
documentLoader,
|