@fedify/vocab-runtime 2.4.0-dev.2063 → 2.4.0-dev.2071

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 (31) hide show
  1. package/deno.json +1 -1
  2. package/dist/internal/portable-dereference.cjs +193 -21
  3. package/dist/internal/portable-dereference.d.cts +155 -15
  4. package/dist/internal/portable-dereference.d.ts +155 -15
  5. package/dist/internal/portable-dereference.js +187 -22
  6. package/dist/mod.cjs +1 -1
  7. package/dist/mod.d.cts +1 -1
  8. package/dist/mod.d.ts +1 -1
  9. package/dist/mod.js +1 -1
  10. package/dist/{portable--NcyA1R_.d.ts → portable-DH3947GK.d.ts} +6 -2
  11. package/dist/{portable-BykOD45s.d.cts → portable-comBI05Y.d.cts} +6 -2
  12. package/dist/tests/{body-CTGqQhNI.cjs → body-BA5q10mr.cjs} +1 -1
  13. package/dist/tests/{body-BN5x-zDQ.mjs → body-XAE-ooHH.mjs} +1 -1
  14. package/dist/tests/body.test.cjs +1 -1
  15. package/dist/tests/body.test.mjs +1 -1
  16. package/dist/tests/decimal.test.cjs +1 -1
  17. package/dist/tests/decimal.test.mjs +1 -1
  18. package/dist/tests/{docloader-BFxwbqMx.mjs → docloader-CKZdC6iZ.mjs} +2 -2
  19. package/dist/tests/{docloader-JGSpG-3l.cjs → docloader-D6BFa7gx.cjs} +2 -2
  20. package/dist/tests/docloader.test.cjs +2 -2
  21. package/dist/tests/docloader.test.mjs +2 -2
  22. package/dist/tests/internal/portable-dereference.test.cjs +87 -0
  23. package/dist/tests/internal/portable-dereference.test.mjs +87 -0
  24. package/dist/tests/{request-BT9FBhk6.mjs → request-DXvwmbWU.mjs} +1 -1
  25. package/dist/tests/{request-jWhPNG9V.cjs → request-D_TFIuTp.cjs} +1 -1
  26. package/dist/tests/request.test.cjs +1 -1
  27. package/dist/tests/request.test.mjs +1 -1
  28. package/package.json +1 -1
  29. package/src/internal/portable-dereference.test.ts +32 -0
  30. package/src/internal/portable-dereference.ts +288 -28
  31. package/src/portable.ts +6 -2
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-runtime",
3
- "version": "2.4.0-dev.2063+366c0362",
3
+ "version": "2.4.0-dev.2071+8b9dccb9",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./src/mod.ts",
@@ -118,24 +118,169 @@ function copyPortableProvenance(from, to) {
118
118
  });
119
119
  }
120
120
  /**
121
- * Rejects a reference from a portable object that would be dereferenced as
122
- * an ordinary HTTP(S) object although it stands for a portable object, i.e.,
123
- * an FEP-ef61 compatible identifier, or a document whose final URL or `@id`
124
- * is a compatible identifier or a portable IRI. Such a document would skip
125
- * the portable object policy, so it is rejected regardless of the
126
- * `crossOrigin` option, except that `crossOrigin: "throw"` makes it throw.
121
+ * Recognizes an FEP-ef61 compatible identifier to dereference as a portable
122
+ * object.
123
+ *
124
+ * @returns `undefined` if the URL is not a compatible identifier; `null` if
125
+ * it is a malformed compatible identifier; otherwise, the portable
126
+ * ID it stands for and the gateway it names.
127
+ * @internal Technically exported for generated vocabulary classes, but not
128
+ * part of the public API contract. This is not considered public API for
129
+ * Semantic Versioning decisions.
130
+ */
131
+ function parseCompatibleEf61Reference(url) {
132
+ if (typeof url === "string") {
133
+ if (!URL.canParse(url)) return void 0;
134
+ url = new URL(url);
135
+ }
136
+ try {
137
+ const id = require_url.fromCompatibleEf61Id(url);
138
+ if (id == null) return void 0;
139
+ return {
140
+ id,
141
+ gateway: new URL(url.origin)
142
+ };
143
+ } catch (error) {
144
+ if (error instanceof TypeError) {
145
+ logger.debug("Invalid FEP-ef61 compatible identifier {url}: {error}", {
146
+ url: url.href,
147
+ error
148
+ });
149
+ return null;
150
+ }
151
+ throw error;
152
+ }
153
+ }
154
+ /**
155
+ * Checks whether a property accessor call on a vocabulary object applies the
156
+ * FEP-ef61 portable object policy, i.e., whether the `verifyPortableObject`
157
+ * option is given or the object is part of a chain of portable objects.
158
+ * In this mode, compatible identifiers are dereferenced as portable objects,
159
+ * and fetched documents that turn out to stand for portable objects are
160
+ * verified as such.
161
+ *
162
+ * @internal Technically exported for generated vocabulary classes, but not
163
+ * part of the public API contract. This is not considered public API for
164
+ * Semantic Versioning decisions.
165
+ */
166
+ function isPortableMode(object, options) {
167
+ return options.verifyPortableObject != null || isInPortableChain(object);
168
+ }
169
+ /**
170
+ * Checks whether an object embedded in a property of a vocabulary object has
171
+ * to be dereferenced by its `@id` and verified as a portable object rather
172
+ * than trusted as embedded, even with `crossOrigin: "trust"`. This is the
173
+ * case in {@link isPortableMode | portable mode} if its `@id` is an FEP-ef61
174
+ * compatible identifier, or a portable IRI whose DID differs from the
175
+ * owner's portable ID.
176
+ *
177
+ * @param parent The object whose property embeds the object.
178
+ * @param ownerId The ID of the object that vouches for embedded objects, or
179
+ * `null` if embedded objects are not trusted by their owner.
180
+ * @param id The `@id` of the embedded object.
181
+ * @param options The options of the accessor.
182
+ * @internal Technically exported for generated vocabulary classes, but not
183
+ * part of the public API contract. This is not considered public API for
184
+ * Semantic Versioning decisions.
185
+ */
186
+ function mustDereferencePortableObject(parent, ownerId, id, options) {
187
+ if (!isPortableMode(parent, options)) return false;
188
+ if (isCompatibleEf61Iri(id)) return true;
189
+ if (!isPortableIri(id)) return false;
190
+ return ownerId == null || !isPortableIri(ownerId) || !require_url.haveSameFe34Origin(ownerId, id);
191
+ }
192
+ const PORTABLE_IRI_PATTERN = /^ap(?:\+ef61)?:/i;
193
+ /**
194
+ * Finds out whether a document fetched as an ordinary HTTP(S) document
195
+ * claims to be a portable object: its final URL is a portable IRI or an
196
+ * FEP-ef61 compatible identifier, or else its `@id` is. The final URL takes
197
+ * precedence, so a document whose `@id` claims another object fails the
198
+ * identity check against the final URL.
199
+ *
200
+ * @param documentUrl The final URL of the document.
201
+ * @param objectId The `@id` of the parsed document.
202
+ * @returns `undefined` if the document does not claim to be a portable
203
+ * object; `null` if the claim is malformed; otherwise, the claim.
204
+ * @internal Technically exported for generated vocabulary classes, but not
205
+ * part of the public API contract. This is not considered public API for
206
+ * Semantic Versioning decisions.
207
+ */
208
+ function getPortableResponseClaim(documentUrl, objectId) {
209
+ if (PORTABLE_IRI_PATTERN.test(documentUrl)) {
210
+ let id;
211
+ try {
212
+ id = require_url.parseIri(documentUrl);
213
+ if (require_url.canonicalizePortableUri(documentUrl) !== require_url.canonicalizePortableUri(require_url.formatIri(id))) return null;
214
+ } catch (error) {
215
+ if (error instanceof TypeError) return null;
216
+ throw error;
217
+ }
218
+ return {
219
+ id,
220
+ inferredGateways: getPortableGatewayCandidates(id)
221
+ };
222
+ }
223
+ for (const url of [documentUrl, objectId]) {
224
+ if (url == null) continue;
225
+ const compatible = parseCompatibleEf61Reference(url);
226
+ if (compatible === null) return null;
227
+ if (compatible != null) return {
228
+ id: compatible.id,
229
+ inferredGateways: [compatible.gateway]
230
+ };
231
+ if (url instanceof URL && isPortableIri(url)) return {
232
+ id: url,
233
+ inferredGateways: getPortableGatewayCandidates(url)
234
+ };
235
+ }
236
+ }
237
+ const unverifiedPortableClaims = /* @__PURE__ */ new WeakSet();
238
+ /**
239
+ * Records that an object fetched as an ordinary HTTP(S) object stands for
240
+ * a portable object if its reference, its final URL, or its `@id` is
241
+ * a portable IRI or an FEP-ef61 compatible identifier. Accessors do not
242
+ * cache such objects in their parents, so that a later call with the
243
+ * `verifyPortableObject` option dereferences and verifies them.
244
+ *
245
+ * @internal Technically exported for generated vocabulary classes, but not
246
+ * part of the public API contract. This is not considered public API for
247
+ * Semantic Versioning decisions.
248
+ */
249
+ function markUnverifiedPortableClaim(object, reference, documentUrl) {
250
+ const objectId = getObjectId(object);
251
+ if (isPortableIri(reference) || isCompatibleEf61Iri(reference) || PORTABLE_IRI_PATTERN.test(documentUrl) || isCompatibleEf61Iri(documentUrl) || objectId != null && (isPortableIri(objectId) || isCompatibleEf61Iri(objectId))) unverifiedPortableClaims.add(object);
252
+ }
253
+ /**
254
+ * Checks whether an object was fetched as an ordinary HTTP(S) object although
255
+ * it stands for a portable object. See {@link markUnverifiedPortableClaim}.
256
+ *
257
+ * @internal Technically exported for generated vocabulary classes, but not
258
+ * part of the public API contract. This is not considered public API for
259
+ * Semantic Versioning decisions.
260
+ */
261
+ function isUnverifiedPortableClaim(object) {
262
+ return unverifiedPortableClaims.has(object);
263
+ }
264
+ /**
265
+ * Rejects a malformed FEP-ef61 compatible identifier found in a reference,
266
+ * the final URL of a fetched document, or its `@id`, when it would be
267
+ * dereferenced as a portable object. It is rejected without a request (or
268
+ * without returning the fetched document), since it cannot be verified as
269
+ * a portable object, and fetching it as an ordinary HTTP(S) object would
270
+ * skip the portable object policy.
127
271
  *
128
272
  * @param url The rejected URL, for the log message.
129
- * @param crossOrigin The `crossOrigin` option of the accessor.
273
+ * @param options The options of the accessor.
130
274
  * @returns Always `null`.
131
- * @throws {Error} If `crossOrigin` is `"throw"`.
275
+ * @throws {Error} If `crossOrigin` is `"throw"` and `suppressError` is not
276
+ * set.
132
277
  * @internal Technically exported for generated vocabulary classes, but not
133
278
  * part of the public API contract. This is not considered public API for
134
279
  * Semantic Versioning decisions.
135
280
  */
136
- function rejectPortableChainReference(url, crossOrigin) {
137
- const message = "Refusing to dereference {url} from a portable object as an ordinary HTTP(S) object, because it stands for an FEP-ef61 portable object that is not verified this way.";
138
- if (crossOrigin === "throw") throw new Error(message.replace("{url}", url));
281
+ function rejectMalformedCompatibleReference(url, options) {
282
+ const message = "Refusing to dereference {url}, because it is a malformed FEP-ef61 compatible identifier, which cannot be verified as a portable object.";
283
+ if (options.crossOrigin === "throw" && !options.suppressError) throw new PortableObjectRejectedError(message.replace("{url}", url));
139
284
  logger.warn(message, { url });
140
285
  return null;
141
286
  }
@@ -243,12 +388,18 @@ function parseGatewayOrigin(gateway) {
243
388
  * The parsed object keeps the loader for its own later dereferences, so
244
389
  * `release()` turns it into a plain pass-through to the underlying loader
245
390
  * once the operation is over.
391
+ *
392
+ * @internal Technically exported for generated vocabulary classes, but not
393
+ * part of the public API contract. This is not considered public API for
394
+ * Semantic Versioning decisions.
246
395
  */
247
396
  function createSnapshotContextLoader(contextLoader) {
397
+ for (let wrapped = snapshotLoaders.get(contextLoader); wrapped?.released; wrapped = snapshotLoaders.get(contextLoader)) contextLoader = wrapped.base;
248
398
  const cache = /* @__PURE__ */ new Map();
249
399
  let released = false;
250
400
  const release = () => {
251
401
  released = true;
402
+ state.released = true;
252
403
  cache.clear();
253
404
  };
254
405
  const loader = async (url, options) => {
@@ -270,11 +421,17 @@ function createSnapshotContextLoader(contextLoader) {
270
421
  }
271
422
  return structuredClone(await promise);
272
423
  };
424
+ const state = {
425
+ base: contextLoader,
426
+ released: false
427
+ };
428
+ snapshotLoaders.set(loader, state);
273
429
  return {
274
430
  loader,
275
431
  release
276
432
  };
277
433
  }
434
+ const snapshotLoaders = /* @__PURE__ */ new WeakMap();
278
435
  /**
279
436
  * The error thrown by {@link dereferencePortableIri} under
280
437
  * `crossOrigin: "throw"` when gateways returned objects but none of them
@@ -301,9 +458,10 @@ var PortableObjectRejection = class {
301
458
  *
302
459
  * Gateways are tried one by one until one of them returns a single-node
303
460
  * document whose `@id`, if any, canonically matches the requested IRI and
304
- * which passes `verifyPortableObject`. When there is no gateway to try, the document
305
- * loader is asked for the portable IRI itself, and its result is validated
306
- * the same way.
461
+ * which passes `verifyPortableObject`. When there is no gateway to try, the
462
+ * document loader is asked for the portable IRI itself, and its result is
463
+ * validated the same way. If the `response` option is given, only that
464
+ * document is validated, and nothing is fetched.
307
465
  *
308
466
  * @returns The parsed object, or `null` if no valid object was retrieved and
309
467
  * `suppressError` is set or the failure was a rejected object
@@ -319,7 +477,10 @@ async function dereferencePortableIri(url, options) {
319
477
  url = require_url.parseIri(url);
320
478
  const lookupUrl = require_url.formatIri(url);
321
479
  const { span } = options;
322
- const gateways = getPortableGatewayCandidates(url, options.gateways);
480
+ const explicitGateways = options.gateways == null ? void 0 : getPortableGatewayCandidates(url, options.gateways);
481
+ const inferredGateways = options.inferredGateways ?? (explicitGateways == null ? getPortableGatewayCandidates(url) : []);
482
+ const gateways = [...inferredGateways];
483
+ for (const gateway of explicitGateways ?? []) if (!gateways.some((g) => g.href === gateway.href)) gateways.push(gateway);
323
484
  const fail = (error) => {
324
485
  span?.setStatus({
325
486
  code: _opentelemetry_api.SpanStatusCode.ERROR,
@@ -340,7 +501,12 @@ async function dereferencePortableIri(url, options) {
340
501
  let expectedId;
341
502
  try {
342
503
  expectedId = require_url.canonicalizePortableUri(lookupUrl);
343
- for (const gateway of gateways) requestUrls.push({
504
+ if (options.response != null) requestUrls.push({
505
+ url: options.response.documentUrl,
506
+ gateway: null,
507
+ response: options.response
508
+ });
509
+ else for (const gateway of gateways) requestUrls.push({
344
510
  url: require_url.toCompatibleEf61Id(url, gateway).href,
345
511
  gateway
346
512
  });
@@ -355,15 +521,14 @@ async function dereferencePortableIri(url, options) {
355
521
  const contextLoader = snapshot.loader;
356
522
  const attempts = [];
357
523
  const { signal } = options;
358
- const explicitGateways = options.gateways == null ? void 0 : gateways;
359
- const gatewayHints = options.gateways == null && gateways.length > 0 ? gateways : void 0;
524
+ const gatewayHints = explicitGateways == null && inferredGateways.length > 0 ? inferredGateways : void 0;
360
525
  const referrer = buildReferrerChain(options.referrer);
361
526
  try {
362
- for (const { url: requestUrl, gateway } of requestUrls) {
527
+ for (const { url: requestUrl, gateway, response } of requestUrls) {
363
528
  signal?.throwIfAborted();
364
529
  let remoteDocument;
365
530
  try {
366
- remoteDocument = await options.documentLoader(requestUrl, signal == null ? void 0 : { signal });
531
+ remoteDocument = response ?? await options.documentLoader(requestUrl, signal == null ? void 0 : { signal });
367
532
  } catch (error) {
368
533
  signal?.throwIfAborted();
369
534
  logger.debug("Failed to fetch {url} from {requestUrl}: {error}", {
@@ -479,12 +644,19 @@ async function checkPortableObjectId(document, expectedId, contextLoader) {
479
644
  //#endregion
480
645
  exports.PortableObjectRejectedError = PortableObjectRejectedError;
481
646
  exports.copyPortableProvenance = copyPortableProvenance;
647
+ exports.createSnapshotContextLoader = createSnapshotContextLoader;
482
648
  exports.dereferencePortableIri = dereferencePortableIri;
483
649
  exports.getPortableGatewayCandidates = getPortableGatewayCandidates;
650
+ exports.getPortableResponseClaim = getPortableResponseClaim;
484
651
  exports.isCompatibleEf61Iri = isCompatibleEf61Iri;
485
652
  exports.isInPortableChain = isInPortableChain;
486
653
  exports.isPortableIri = isPortableIri;
654
+ exports.isPortableMode = isPortableMode;
487
655
  exports.isUnsecuredPortableObject = isUnsecuredPortableObject;
656
+ exports.isUnverifiedPortableClaim = isUnverifiedPortableClaim;
657
+ exports.markUnverifiedPortableClaim = markUnverifiedPortableClaim;
658
+ exports.mustDereferencePortableObject = mustDereferencePortableObject;
659
+ exports.parseCompatibleEf61Reference = parseCompatibleEf61Reference;
488
660
  exports.recordPortableReferrer = recordPortableReferrer;
489
- exports.rejectPortableChainReference = rejectPortableChainReference;
661
+ exports.rejectMalformedCompatibleReference = rejectMalformedCompatibleReference;
490
662
  exports.warnUnverifiableEmbeddedObject = warnUnverifiableEmbeddedObject;
@@ -1,6 +1,6 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { n as DocumentLoader } from "../docloader-Dr8wEkif.cjs";
3
- import { r as PortableObjectVerifier } from "../portable-BykOD45s.cjs";
2
+ import { n as DocumentLoader, s as RemoteDocument } from "../docloader-Dr8wEkif.cjs";
3
+ import { r as PortableObjectVerifier } from "../portable-comBI05Y.cjs";
4
4
  import { Span, TracerProvider } from "@opentelemetry/api";
5
5
 
6
6
  //#region src/internal/portable-dereference.d.ts
@@ -69,22 +69,128 @@ declare function recordPortableReferrer(parent: object, child: unknown, property
69
69
  */
70
70
  declare function copyPortableProvenance(from: object, to: object): void;
71
71
  /**
72
- * Rejects a reference from a portable object that would be dereferenced as
73
- * an ordinary HTTP(S) object although it stands for a portable object, i.e.,
74
- * an FEP-ef61 compatible identifier, or a document whose final URL or `@id`
75
- * is a compatible identifier or a portable IRI. Such a document would skip
76
- * the portable object policy, so it is rejected regardless of the
77
- * `crossOrigin` option, except that `crossOrigin: "throw"` makes it throw.
72
+ * Recognizes an FEP-ef61 compatible identifier to dereference as a portable
73
+ * object.
74
+ *
75
+ * @returns `undefined` if the URL is not a compatible identifier; `null` if
76
+ * it is a malformed compatible identifier; otherwise, the portable
77
+ * ID it stands for and the gateway it names.
78
+ * @internal Technically exported for generated vocabulary classes, but not
79
+ * part of the public API contract. This is not considered public API for
80
+ * Semantic Versioning decisions.
81
+ */
82
+ declare function parseCompatibleEf61Reference(url: URL | string): {
83
+ readonly id: URL;
84
+ readonly gateway: URL;
85
+ } | null | undefined;
86
+ /**
87
+ * Checks whether a property accessor call on a vocabulary object applies the
88
+ * FEP-ef61 portable object policy, i.e., whether the `verifyPortableObject`
89
+ * option is given or the object is part of a chain of portable objects.
90
+ * In this mode, compatible identifiers are dereferenced as portable objects,
91
+ * and fetched documents that turn out to stand for portable objects are
92
+ * verified as such.
93
+ *
94
+ * @internal Technically exported for generated vocabulary classes, but not
95
+ * part of the public API contract. This is not considered public API for
96
+ * Semantic Versioning decisions.
97
+ */
98
+ declare function isPortableMode(object: object, options: {
99
+ readonly verifyPortableObject?: PortableObjectVerifier;
100
+ }): boolean;
101
+ /**
102
+ * Checks whether an object embedded in a property of a vocabulary object has
103
+ * to be dereferenced by its `@id` and verified as a portable object rather
104
+ * than trusted as embedded, even with `crossOrigin: "trust"`. This is the
105
+ * case in {@link isPortableMode | portable mode} if its `@id` is an FEP-ef61
106
+ * compatible identifier, or a portable IRI whose DID differs from the
107
+ * owner's portable ID.
108
+ *
109
+ * @param parent The object whose property embeds the object.
110
+ * @param ownerId The ID of the object that vouches for embedded objects, or
111
+ * `null` if embedded objects are not trusted by their owner.
112
+ * @param id The `@id` of the embedded object.
113
+ * @param options The options of the accessor.
114
+ * @internal Technically exported for generated vocabulary classes, but not
115
+ * part of the public API contract. This is not considered public API for
116
+ * Semantic Versioning decisions.
117
+ */
118
+ declare function mustDereferencePortableObject(parent: object, ownerId: URL | null, id: URL, options: {
119
+ readonly verifyPortableObject?: PortableObjectVerifier;
120
+ }): boolean;
121
+ /**
122
+ * The portable object that a document fetched as an ordinary HTTP(S)
123
+ * document claims to be.
124
+ *
125
+ * @internal
126
+ */
127
+ interface PortableResponseClaim {
128
+ /** The portable ID that the document has to have. */
129
+ readonly id: URL;
130
+ /**
131
+ * The gateways inferred from the document's URL or `@id`, which are
132
+ * reported to the verifier as gateway hints.
133
+ */
134
+ readonly inferredGateways: readonly URL[];
135
+ }
136
+ /**
137
+ * Finds out whether a document fetched as an ordinary HTTP(S) document
138
+ * claims to be a portable object: its final URL is a portable IRI or an
139
+ * FEP-ef61 compatible identifier, or else its `@id` is. The final URL takes
140
+ * precedence, so a document whose `@id` claims another object fails the
141
+ * identity check against the final URL.
142
+ *
143
+ * @param documentUrl The final URL of the document.
144
+ * @param objectId The `@id` of the parsed document.
145
+ * @returns `undefined` if the document does not claim to be a portable
146
+ * object; `null` if the claim is malformed; otherwise, the claim.
147
+ * @internal Technically exported for generated vocabulary classes, but not
148
+ * part of the public API contract. This is not considered public API for
149
+ * Semantic Versioning decisions.
150
+ */
151
+ declare function getPortableResponseClaim(documentUrl: string, objectId: URL | null): PortableResponseClaim | null | undefined;
152
+ /**
153
+ * Records that an object fetched as an ordinary HTTP(S) object stands for
154
+ * a portable object if its reference, its final URL, or its `@id` is
155
+ * a portable IRI or an FEP-ef61 compatible identifier. Accessors do not
156
+ * cache such objects in their parents, so that a later call with the
157
+ * `verifyPortableObject` option dereferences and verifies them.
158
+ *
159
+ * @internal Technically exported for generated vocabulary classes, but not
160
+ * part of the public API contract. This is not considered public API for
161
+ * Semantic Versioning decisions.
162
+ */
163
+ declare function markUnverifiedPortableClaim(object: object, reference: URL, documentUrl: string): void;
164
+ /**
165
+ * Checks whether an object was fetched as an ordinary HTTP(S) object although
166
+ * it stands for a portable object. See {@link markUnverifiedPortableClaim}.
167
+ *
168
+ * @internal Technically exported for generated vocabulary classes, but not
169
+ * part of the public API contract. This is not considered public API for
170
+ * Semantic Versioning decisions.
171
+ */
172
+ declare function isUnverifiedPortableClaim(object: object): boolean;
173
+ /**
174
+ * Rejects a malformed FEP-ef61 compatible identifier found in a reference,
175
+ * the final URL of a fetched document, or its `@id`, when it would be
176
+ * dereferenced as a portable object. It is rejected without a request (or
177
+ * without returning the fetched document), since it cannot be verified as
178
+ * a portable object, and fetching it as an ordinary HTTP(S) object would
179
+ * skip the portable object policy.
78
180
  *
79
181
  * @param url The rejected URL, for the log message.
80
- * @param crossOrigin The `crossOrigin` option of the accessor.
182
+ * @param options The options of the accessor.
81
183
  * @returns Always `null`.
82
- * @throws {Error} If `crossOrigin` is `"throw"`.
184
+ * @throws {Error} If `crossOrigin` is `"throw"` and `suppressError` is not
185
+ * set.
83
186
  * @internal Technically exported for generated vocabulary classes, but not
84
187
  * part of the public API contract. This is not considered public API for
85
188
  * Semantic Versioning decisions.
86
189
  */
87
- declare function rejectPortableChainReference(url: string, crossOrigin: "ignore" | "throw" | "trust" | undefined): null;
190
+ declare function rejectMalformedCompatibleReference(url: string, options: {
191
+ readonly crossOrigin?: "ignore" | "throw" | "trust";
192
+ readonly suppressError?: boolean;
193
+ }): null;
88
194
  /**
89
195
  * Logs that an embedded object without `@id` in an object accepted without
90
196
  * an integrity proof is dropped, because it cannot be dereferenced and
@@ -116,6 +222,25 @@ declare function isPortableIri(url: URL): boolean;
116
222
  */
117
223
  declare function getPortableGatewayCandidates(url: URL, gateways?: readonly (string | URL)[]): URL[];
118
224
  /**
225
+ * Creates a context loader that returns the same context documents for the
226
+ * whole dereference operation, so that the identity check, the proof
227
+ * verifier, and the parser interpret the fetched document identically even
228
+ * if the underlying loader is nondeterministic. Failed loads are not
229
+ * remembered, so a transient failure does not affect the next gateway.
230
+ *
231
+ * The parsed object keeps the loader for its own later dereferences, so
232
+ * `release()` turns it into a plain pass-through to the underlying loader
233
+ * once the operation is over.
234
+ *
235
+ * @internal Technically exported for generated vocabulary classes, but not
236
+ * part of the public API contract. This is not considered public API for
237
+ * Semantic Versioning decisions.
238
+ */
239
+ declare function createSnapshotContextLoader(contextLoader: DocumentLoader): {
240
+ loader: DocumentLoader;
241
+ release: () => void;
242
+ };
243
+ /**
119
244
  * Options for {@link dereferencePortableIri}.
120
245
  *
121
246
  * @internal Technically exported for generated vocabulary classes, but not
@@ -127,6 +252,20 @@ interface DereferencePortableIriOptions<T> {
127
252
  contextLoader: DocumentLoader;
128
253
  tracerProvider: TracerProvider;
129
254
  gateways?: readonly (string | URL)[];
255
+ /**
256
+ * The gateways inferred from where the reference came from, e.g., the
257
+ * gateway of a compatible identifier. When given, they replace the
258
+ * `@gateway` location hints of the IRI, are asked before the explicit
259
+ * `gateways`, and are reported to the verifier as gateway hints unless
260
+ * `gateways` is given.
261
+ */
262
+ inferredGateways?: readonly URL[];
263
+ /**
264
+ * An already fetched document to validate instead of fetching the object
265
+ * from gateways. It is validated the same way as a gateway's response,
266
+ * and nothing else is tried if it is rejected.
267
+ */
268
+ response?: RemoteDocument;
130
269
  verifyPortableObject?: PortableObjectVerifier;
131
270
  referrer?: PortableReferrerLink;
132
271
  suppressError?: boolean;
@@ -158,9 +297,10 @@ declare class PortableObjectRejectedError extends Error {
158
297
  *
159
298
  * Gateways are tried one by one until one of them returns a single-node
160
299
  * document whose `@id`, if any, canonically matches the requested IRI and
161
- * which passes `verifyPortableObject`. When there is no gateway to try, the document
162
- * loader is asked for the portable IRI itself, and its result is validated
163
- * the same way.
300
+ * which passes `verifyPortableObject`. When there is no gateway to try, the
301
+ * document loader is asked for the portable IRI itself, and its result is
302
+ * validated the same way. If the `response` option is given, only that
303
+ * document is validated, and nothing is fetched.
164
304
  *
165
305
  * @returns The parsed object, or `null` if no valid object was retrieved and
166
306
  * `suppressError` is set or the failure was a rejected object
@@ -176,4 +316,4 @@ declare function dereferencePortableIri<T extends {
176
316
  id: URL | null;
177
317
  }>(url: URL, options: DereferencePortableIriOptions<T>): Promise<T | null>;
178
318
  //#endregion
179
- export { DereferencePortableIriOptions, PortableObjectRejectedError, PortableReferrerLink, copyPortableProvenance, dereferencePortableIri, getPortableGatewayCandidates, isCompatibleEf61Iri, isInPortableChain, isPortableIri, isUnsecuredPortableObject, recordPortableReferrer, rejectPortableChainReference, warnUnverifiableEmbeddedObject };
319
+ export { DereferencePortableIriOptions, PortableObjectRejectedError, PortableReferrerLink, PortableResponseClaim, copyPortableProvenance, createSnapshotContextLoader, dereferencePortableIri, getPortableGatewayCandidates, getPortableResponseClaim, isCompatibleEf61Iri, isInPortableChain, isPortableIri, isPortableMode, isUnsecuredPortableObject, isUnverifiedPortableClaim, markUnverifiedPortableClaim, mustDereferencePortableObject, parseCompatibleEf61Reference, recordPortableReferrer, rejectMalformedCompatibleReference, warnUnverifiableEmbeddedObject };