@fedify/vocab-tools 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.
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-tools",
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"
package/dist/mod.cjs CHANGED
@@ -8,7 +8,7 @@ let yaml = require("yaml");
8
8
  let es_toolkit = require("es-toolkit");
9
9
  //#region deno.json
10
10
  var name = "@fedify/vocab-tools";
11
- var version = "2.4.0-dev.2063+366c0362";
11
+ var version = "2.4.0-dev.2071+8b9dccb9";
12
12
  //#endregion
13
13
  //#region src/type.ts
14
14
  const HEURISTICS_CONTEXTS = [
@@ -1673,13 +1673,22 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1673
1673
  ${JSON.stringify(version)},
1674
1674
  );
1675
1675
  return await tracer.startActiveSpan("activitypub.lookup_object", async (span) => {
1676
- if (isPortableIri(url)) {
1676
+ const dereferencePortable = async (
1677
+ portableUrl: URL,
1678
+ extra: {
1679
+ inferredGateways?: readonly URL[];
1680
+ response?: RemoteDocument;
1681
+ contextLoader?: DocumentLoader;
1682
+ } = {},
1683
+ ) => {
1677
1684
  try {
1678
- const obj = await dereferencePortableIri(url, {
1685
+ const obj = await dereferencePortableIri(portableUrl, {
1679
1686
  documentLoader,
1680
- contextLoader,
1687
+ contextLoader: extra.contextLoader ?? contextLoader,
1681
1688
  tracerProvider,
1682
1689
  gateways: options.gateways,
1690
+ inferredGateways: extra.inferredGateways,
1691
+ response: extra.response,
1683
1692
  verifyPortableObject: options.verifyPortableObject,
1684
1693
  referrer: {
1685
1694
  object: this,
@@ -1697,7 +1706,10 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1697
1706
  }),
1698
1707
  });
1699
1708
  if (obj != null) {
1700
- span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1709
+ span.setAttribute(
1710
+ "activitypub.object.id",
1711
+ (obj.id ?? portableUrl).href,
1712
+ );
1701
1713
  span.setAttribute(
1702
1714
  "activitypub.object.type",
1703
1715
  // @ts-ignore: obj.constructor always has a typeId.
@@ -1714,12 +1726,20 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1714
1726
  } finally {
1715
1727
  span.end();
1716
1728
  }
1717
- }
1729
+ };
1730
+ if (isPortableIri(url)) return await dereferencePortable(url);
1718
1731
  const lookupUrl = formatIri(url);
1719
- const inPortableChain = isInPortableChain(this);
1720
- if (inPortableChain && isCompatibleEf61Iri(url)) {
1721
- span.end();
1722
- return rejectPortableChainReference(lookupUrl, options.crossOrigin);
1732
+ const portableMode = isPortableMode(this, options);
1733
+ if (portableMode) {
1734
+ const compatible = parseCompatibleEf61Reference(url);
1735
+ if (compatible === null) {
1736
+ span.end();
1737
+ return rejectMalformedCompatibleReference(lookupUrl, options);
1738
+ } else if (compatible != null) {
1739
+ return await dereferencePortable(compatible.id, {
1740
+ inferredGateways: [compatible.gateway],
1741
+ });
1742
+ }
1723
1743
  }
1724
1744
  let fetchResult: RemoteDocument;
1725
1745
  try {
@@ -1740,63 +1760,90 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1740
1760
  throw error;
1741
1761
  }
1742
1762
  const { document, documentUrl } = fetchResult;
1743
- const baseUrl = parseIri(documentUrl);
1763
+ // In portable mode, the document may turn out to be a portable object,
1764
+ // which has to be verified with the same context documents:
1765
+ const snapshot = portableMode
1766
+ ? createSnapshotContextLoader(contextLoader)
1767
+ : null;
1744
1768
  try {
1745
- const obj = await this.#${property.singularName}_fromJsonLd(
1746
- document,
1747
- { documentLoader, contextLoader, tracerProvider, baseUrl }
1748
- );
1749
- if (
1750
- inPortableChain &&
1751
- (isCompatibleEf61Iri(documentUrl) ||
1752
- (obj.id != null &&
1753
- (isPortableIri(obj.id) || isCompatibleEf61Iri(obj.id))))
1754
- ) {
1755
- return rejectPortableChainReference(
1756
- documentUrl,
1757
- options.crossOrigin,
1769
+ let claim: PortableResponseClaim | null | undefined;
1770
+ try {
1771
+ const baseUrl = parseIri(documentUrl);
1772
+ const obj = await this.#${property.singularName}_fromJsonLd(
1773
+ document,
1774
+ {
1775
+ documentLoader,
1776
+ contextLoader: snapshot?.loader ?? contextLoader,
1777
+ tracerProvider,
1778
+ baseUrl,
1779
+ }
1758
1780
  );
1759
- }
1760
- if (obj?.id != null && !isTrustedIriOrigin(options, obj.id, baseUrl)) {
1761
- if (options.crossOrigin === "throw") {
1762
- throw new Error(
1763
- "The object's @id (" + obj.id.href + ") has a different origin " +
1764
- "than the document URL (" + baseUrl.href + "); refusing to return " +
1765
- "the object. If you want to bypass this check and are aware of" +
1766
- 'the security implications, set the crossOrigin option to "trust".'
1781
+ if (snapshot == null) {
1782
+ markUnverifiedPortableClaim(obj, url, documentUrl);
1783
+ } else {
1784
+ claim = getPortableResponseClaim(documentUrl, obj.id);
1785
+ }
1786
+ if (claim === undefined) {
1787
+ if (
1788
+ obj?.id != null &&
1789
+ !isTrustedIriOrigin(options, obj.id, baseUrl)
1790
+ ) {
1791
+ if (options.crossOrigin === "throw") {
1792
+ throw new Error(
1793
+ "The object's @id (" + obj.id.href + ") has a different origin " +
1794
+ "than the document URL (" + baseUrl.href + "); refusing to return " +
1795
+ "the object. If you want to bypass this check and are aware of" +
1796
+ 'the security implications, set the crossOrigin option to "trust".'
1797
+ );
1798
+ }
1799
+ getLogger(["fedify", "vocab"]).warn(
1800
+ "The object's @id ({objectId}) has a different origin than the document " +
1801
+ "URL ({documentUrl}); refusing to return the object. If you want to " +
1802
+ "bypass this check and are aware of the security implications, " +
1803
+ 'set the crossOrigin option to "trust".',
1804
+ { ...fetchResult, objectId: obj.id.href },
1805
+ );
1806
+ span.end();
1807
+ return null;
1808
+ }
1809
+ span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1810
+ span.setAttribute(
1811
+ "activitypub.object.type",
1812
+ // @ts-ignore: obj.constructor always has a typeId.
1813
+ obj.constructor.typeId.href
1767
1814
  );
1815
+ span.end();
1816
+ return obj;
1768
1817
  }
1769
- getLogger(["fedify", "vocab"]).warn(
1770
- "The object's @id ({objectId}) has a different origin than the document " +
1771
- "URL ({documentUrl}); refusing to return the object. If you want to " +
1772
- "bypass this check and are aware of the security implications, " +
1773
- 'set the crossOrigin option to "trust".',
1774
- { ...fetchResult, objectId: obj.id.href },
1775
- );
1776
- return null;
1818
+ } catch (e) {
1819
+ if (options.suppressError) {
1820
+ getLogger(["fedify", "vocab"]).error(
1821
+ "Failed to parse {url}: {error}",
1822
+ { error: e, url: lookupUrl }
1823
+ );
1824
+ span.end();
1825
+ return null;
1826
+ }
1827
+ span.setStatus({
1828
+ code: SpanStatusCode.ERROR,
1829
+ message: String(e),
1830
+ });
1831
+ span.end();
1832
+ throw e;
1777
1833
  }
1778
- span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1779
- span.setAttribute(
1780
- "activitypub.object.type",
1781
- // @ts-ignore: obj.constructor always has a typeId.
1782
- obj.constructor.typeId.href
1783
- );
1784
- return obj;
1785
- } catch (e) {
1786
- if (options.suppressError) {
1787
- getLogger(["fedify", "vocab"]).error(
1788
- "Failed to parse {url}: {error}",
1789
- { error: e, url: lookupUrl }
1790
- );
1791
- return null;
1834
+ // The document stands for a portable object, so it is verified as
1835
+ // one instead of being trusted because of where it came from:
1836
+ if (claim === null) {
1837
+ span.end();
1838
+ return rejectMalformedCompatibleReference(documentUrl, options);
1792
1839
  }
1793
- span.setStatus({
1794
- code: SpanStatusCode.ERROR,
1795
- message: String(e),
1840
+ return await dereferencePortable(claim.id, {
1841
+ inferredGateways: claim.inferredGateways,
1842
+ response: fetchResult,
1843
+ contextLoader: snapshot?.loader,
1796
1844
  });
1797
- throw e;
1798
1845
  } finally {
1799
- span.end();
1846
+ snapshot?.release();
1800
1847
  }
1801
1848
  });
1802
1849
  }
@@ -1918,7 +1965,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1918
1965
  } else if (
1919
1966
  !isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
1920
1967
  isUnsecuredPortableObject(this) ||
1921
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))
1968
+ mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
1922
1969
  ) {
1923
1970
  v = v.id;
1924
1971
  }
@@ -1927,6 +1974,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1927
1974
  const fetched =
1928
1975
  await this.#fetch${(0, es_toolkit.pascalCase)(property.singularName)}(v, options);
1929
1976
  if (fetched == null) return null;
1977
+ // Not cached, so that it is verified when the portable object
1978
+ // policy applies later:
1979
+ if (isUnverifiedPortableClaim(fetched)) return fetched;
1930
1980
  this.${await getFieldName(property.uri)}[0] = fetched;
1931
1981
  this.${await getFieldName(property.uri, "#_trust")}.add(0);
1932
1982
  this._cachedJsonLd = undefined;
@@ -1962,7 +2012,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1962
2012
  if (v?.id != null &&
1963
2013
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
1964
2014
  isUnsecuredPortableObject(this) ||
1965
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))) &&
2015
+ mustDereferencePortableObject(
2016
+ this, ${trustOwner}, v.id, options,
2017
+ )) &&
1966
2018
  !this.${await getFieldName(property.uri, "#_trust")}.has(0)) {
1967
2019
  if (options.crossOrigin === "throw") {
1968
2020
  throw new Error(
@@ -2039,7 +2091,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2039
2091
  } else if (
2040
2092
  !isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
2041
2093
  isUnsecuredPortableObject(this) ||
2042
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))
2094
+ mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
2043
2095
  ) {
2044
2096
  v = v.id;
2045
2097
  }
@@ -2048,6 +2100,12 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2048
2100
  const fetched =
2049
2101
  await this.#fetch${(0, es_toolkit.pascalCase)(property.singularName)}(v, options);
2050
2102
  if (fetched == null) continue;
2103
+ // Not cached, so that it is verified when the portable object
2104
+ // policy applies later:
2105
+ if (isUnverifiedPortableClaim(fetched)) {
2106
+ yield fetched;
2107
+ continue;
2108
+ }
2051
2109
  vs[i] = fetched;
2052
2110
  this.${await getFieldName(property.uri, "#_trust")}.add(i);
2053
2111
  this._cachedJsonLd = undefined;
@@ -2084,7 +2142,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2084
2142
  if (v?.id != null &&
2085
2143
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
2086
2144
  isUnsecuredPortableObject(this) ||
2087
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))) &&
2145
+ mustDereferencePortableObject(
2146
+ this, ${trustOwner}, v.id, options,
2147
+ )) &&
2088
2148
  !this.${await getFieldName(property.uri, "#_trust")}.has(i)) {
2089
2149
  if (options.crossOrigin === "throw") {
2090
2150
  throw new Error(
@@ -2129,13 +2189,19 @@ const INTERNAL_RUNTIME_IMPORTS = [
2129
2189
  ].join(",\n ");
2130
2190
  const PORTABLE_DEREFERENCE_IMPORTS = [
2131
2191
  "copyPortableProvenance",
2192
+ "createSnapshotContextLoader",
2132
2193
  "dereferencePortableIri",
2133
- "isCompatibleEf61Iri",
2134
- "isInPortableChain",
2194
+ "getPortableResponseClaim",
2135
2195
  "isPortableIri",
2196
+ "isPortableMode",
2136
2197
  "isUnsecuredPortableObject",
2198
+ "isUnverifiedPortableClaim",
2199
+ "markUnverifiedPortableClaim",
2200
+ "mustDereferencePortableObject",
2201
+ "parseCompatibleEf61Reference",
2202
+ "type PortableResponseClaim",
2137
2203
  "recordPortableReferrer",
2138
- "rejectPortableChainReference",
2204
+ "rejectMalformedCompatibleReference",
2139
2205
  "warnUnverifiableEmbeddedObject"
2140
2206
  ].join(",\n ");
2141
2207
  const SIGNED_REPRESENTATION_IMPORTS = [
package/dist/mod.js CHANGED
@@ -7,7 +7,7 @@ import { parse } from "yaml";
7
7
  import { pascalCase } from "es-toolkit";
8
8
  //#region deno.json
9
9
  var name = "@fedify/vocab-tools";
10
- var version = "2.4.0-dev.2063+366c0362";
10
+ var version = "2.4.0-dev.2071+8b9dccb9";
11
11
  //#endregion
12
12
  //#region src/type.ts
13
13
  const HEURISTICS_CONTEXTS = [
@@ -1672,13 +1672,22 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1672
1672
  ${JSON.stringify(version)},
1673
1673
  );
1674
1674
  return await tracer.startActiveSpan("activitypub.lookup_object", async (span) => {
1675
- if (isPortableIri(url)) {
1675
+ const dereferencePortable = async (
1676
+ portableUrl: URL,
1677
+ extra: {
1678
+ inferredGateways?: readonly URL[];
1679
+ response?: RemoteDocument;
1680
+ contextLoader?: DocumentLoader;
1681
+ } = {},
1682
+ ) => {
1676
1683
  try {
1677
- const obj = await dereferencePortableIri(url, {
1684
+ const obj = await dereferencePortableIri(portableUrl, {
1678
1685
  documentLoader,
1679
- contextLoader,
1686
+ contextLoader: extra.contextLoader ?? contextLoader,
1680
1687
  tracerProvider,
1681
1688
  gateways: options.gateways,
1689
+ inferredGateways: extra.inferredGateways,
1690
+ response: extra.response,
1682
1691
  verifyPortableObject: options.verifyPortableObject,
1683
1692
  referrer: {
1684
1693
  object: this,
@@ -1696,7 +1705,10 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1696
1705
  }),
1697
1706
  });
1698
1707
  if (obj != null) {
1699
- span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1708
+ span.setAttribute(
1709
+ "activitypub.object.id",
1710
+ (obj.id ?? portableUrl).href,
1711
+ );
1700
1712
  span.setAttribute(
1701
1713
  "activitypub.object.type",
1702
1714
  // @ts-ignore: obj.constructor always has a typeId.
@@ -1713,12 +1725,20 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1713
1725
  } finally {
1714
1726
  span.end();
1715
1727
  }
1716
- }
1728
+ };
1729
+ if (isPortableIri(url)) return await dereferencePortable(url);
1717
1730
  const lookupUrl = formatIri(url);
1718
- const inPortableChain = isInPortableChain(this);
1719
- if (inPortableChain && isCompatibleEf61Iri(url)) {
1720
- span.end();
1721
- return rejectPortableChainReference(lookupUrl, options.crossOrigin);
1731
+ const portableMode = isPortableMode(this, options);
1732
+ if (portableMode) {
1733
+ const compatible = parseCompatibleEf61Reference(url);
1734
+ if (compatible === null) {
1735
+ span.end();
1736
+ return rejectMalformedCompatibleReference(lookupUrl, options);
1737
+ } else if (compatible != null) {
1738
+ return await dereferencePortable(compatible.id, {
1739
+ inferredGateways: [compatible.gateway],
1740
+ });
1741
+ }
1722
1742
  }
1723
1743
  let fetchResult: RemoteDocument;
1724
1744
  try {
@@ -1739,63 +1759,90 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1739
1759
  throw error;
1740
1760
  }
1741
1761
  const { document, documentUrl } = fetchResult;
1742
- const baseUrl = parseIri(documentUrl);
1762
+ // In portable mode, the document may turn out to be a portable object,
1763
+ // which has to be verified with the same context documents:
1764
+ const snapshot = portableMode
1765
+ ? createSnapshotContextLoader(contextLoader)
1766
+ : null;
1743
1767
  try {
1744
- const obj = await this.#${property.singularName}_fromJsonLd(
1745
- document,
1746
- { documentLoader, contextLoader, tracerProvider, baseUrl }
1747
- );
1748
- if (
1749
- inPortableChain &&
1750
- (isCompatibleEf61Iri(documentUrl) ||
1751
- (obj.id != null &&
1752
- (isPortableIri(obj.id) || isCompatibleEf61Iri(obj.id))))
1753
- ) {
1754
- return rejectPortableChainReference(
1755
- documentUrl,
1756
- options.crossOrigin,
1768
+ let claim: PortableResponseClaim | null | undefined;
1769
+ try {
1770
+ const baseUrl = parseIri(documentUrl);
1771
+ const obj = await this.#${property.singularName}_fromJsonLd(
1772
+ document,
1773
+ {
1774
+ documentLoader,
1775
+ contextLoader: snapshot?.loader ?? contextLoader,
1776
+ tracerProvider,
1777
+ baseUrl,
1778
+ }
1757
1779
  );
1758
- }
1759
- if (obj?.id != null && !isTrustedIriOrigin(options, obj.id, baseUrl)) {
1760
- if (options.crossOrigin === "throw") {
1761
- throw new Error(
1762
- "The object's @id (" + obj.id.href + ") has a different origin " +
1763
- "than the document URL (" + baseUrl.href + "); refusing to return " +
1764
- "the object. If you want to bypass this check and are aware of" +
1765
- 'the security implications, set the crossOrigin option to "trust".'
1780
+ if (snapshot == null) {
1781
+ markUnverifiedPortableClaim(obj, url, documentUrl);
1782
+ } else {
1783
+ claim = getPortableResponseClaim(documentUrl, obj.id);
1784
+ }
1785
+ if (claim === undefined) {
1786
+ if (
1787
+ obj?.id != null &&
1788
+ !isTrustedIriOrigin(options, obj.id, baseUrl)
1789
+ ) {
1790
+ if (options.crossOrigin === "throw") {
1791
+ throw new Error(
1792
+ "The object's @id (" + obj.id.href + ") has a different origin " +
1793
+ "than the document URL (" + baseUrl.href + "); refusing to return " +
1794
+ "the object. If you want to bypass this check and are aware of" +
1795
+ 'the security implications, set the crossOrigin option to "trust".'
1796
+ );
1797
+ }
1798
+ getLogger(["fedify", "vocab"]).warn(
1799
+ "The object's @id ({objectId}) has a different origin than the document " +
1800
+ "URL ({documentUrl}); refusing to return the object. If you want to " +
1801
+ "bypass this check and are aware of the security implications, " +
1802
+ 'set the crossOrigin option to "trust".',
1803
+ { ...fetchResult, objectId: obj.id.href },
1804
+ );
1805
+ span.end();
1806
+ return null;
1807
+ }
1808
+ span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1809
+ span.setAttribute(
1810
+ "activitypub.object.type",
1811
+ // @ts-ignore: obj.constructor always has a typeId.
1812
+ obj.constructor.typeId.href
1766
1813
  );
1814
+ span.end();
1815
+ return obj;
1767
1816
  }
1768
- getLogger(["fedify", "vocab"]).warn(
1769
- "The object's @id ({objectId}) has a different origin than the document " +
1770
- "URL ({documentUrl}); refusing to return the object. If you want to " +
1771
- "bypass this check and are aware of the security implications, " +
1772
- 'set the crossOrigin option to "trust".',
1773
- { ...fetchResult, objectId: obj.id.href },
1774
- );
1775
- return null;
1817
+ } catch (e) {
1818
+ if (options.suppressError) {
1819
+ getLogger(["fedify", "vocab"]).error(
1820
+ "Failed to parse {url}: {error}",
1821
+ { error: e, url: lookupUrl }
1822
+ );
1823
+ span.end();
1824
+ return null;
1825
+ }
1826
+ span.setStatus({
1827
+ code: SpanStatusCode.ERROR,
1828
+ message: String(e),
1829
+ });
1830
+ span.end();
1831
+ throw e;
1776
1832
  }
1777
- span.setAttribute("activitypub.object.id", (obj.id ?? url).href);
1778
- span.setAttribute(
1779
- "activitypub.object.type",
1780
- // @ts-ignore: obj.constructor always has a typeId.
1781
- obj.constructor.typeId.href
1782
- );
1783
- return obj;
1784
- } catch (e) {
1785
- if (options.suppressError) {
1786
- getLogger(["fedify", "vocab"]).error(
1787
- "Failed to parse {url}: {error}",
1788
- { error: e, url: lookupUrl }
1789
- );
1790
- return null;
1833
+ // The document stands for a portable object, so it is verified as
1834
+ // one instead of being trusted because of where it came from:
1835
+ if (claim === null) {
1836
+ span.end();
1837
+ return rejectMalformedCompatibleReference(documentUrl, options);
1791
1838
  }
1792
- span.setStatus({
1793
- code: SpanStatusCode.ERROR,
1794
- message: String(e),
1839
+ return await dereferencePortable(claim.id, {
1840
+ inferredGateways: claim.inferredGateways,
1841
+ response: fetchResult,
1842
+ contextLoader: snapshot?.loader,
1795
1843
  });
1796
- throw e;
1797
1844
  } finally {
1798
- span.end();
1845
+ snapshot?.release();
1799
1846
  }
1800
1847
  });
1801
1848
  }
@@ -1917,7 +1964,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1917
1964
  } else if (
1918
1965
  !isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
1919
1966
  isUnsecuredPortableObject(this) ||
1920
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))
1967
+ mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
1921
1968
  ) {
1922
1969
  v = v.id;
1923
1970
  }
@@ -1926,6 +1973,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1926
1973
  const fetched =
1927
1974
  await this.#fetch${pascalCase(property.singularName)}(v, options);
1928
1975
  if (fetched == null) return null;
1976
+ // Not cached, so that it is verified when the portable object
1977
+ // policy applies later:
1978
+ if (isUnverifiedPortableClaim(fetched)) return fetched;
1929
1979
  this.${await getFieldName(property.uri)}[0] = fetched;
1930
1980
  this.${await getFieldName(property.uri, "#_trust")}.add(0);
1931
1981
  this._cachedJsonLd = undefined;
@@ -1961,7 +2011,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
1961
2011
  if (v?.id != null &&
1962
2012
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
1963
2013
  isUnsecuredPortableObject(this) ||
1964
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))) &&
2014
+ mustDereferencePortableObject(
2015
+ this, ${trustOwner}, v.id, options,
2016
+ )) &&
1965
2017
  !this.${await getFieldName(property.uri, "#_trust")}.has(0)) {
1966
2018
  if (options.crossOrigin === "throw") {
1967
2019
  throw new Error(
@@ -2038,7 +2090,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2038
2090
  } else if (
2039
2091
  !isTrustedIriOrigin(options, v.id, ${trustOwner}) ||
2040
2092
  isUnsecuredPortableObject(this) ||
2041
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))
2093
+ mustDereferencePortableObject(this, ${trustOwner}, v.id, options)
2042
2094
  ) {
2043
2095
  v = v.id;
2044
2096
  }
@@ -2047,6 +2099,12 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2047
2099
  const fetched =
2048
2100
  await this.#fetch${pascalCase(property.singularName)}(v, options);
2049
2101
  if (fetched == null) continue;
2102
+ // Not cached, so that it is verified when the portable object
2103
+ // policy applies later:
2104
+ if (isUnverifiedPortableClaim(fetched)) {
2105
+ yield fetched;
2106
+ continue;
2107
+ }
2050
2108
  vs[i] = fetched;
2051
2109
  this.${await getFieldName(property.uri, "#_trust")}.add(i);
2052
2110
  this._cachedJsonLd = undefined;
@@ -2083,7 +2141,9 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2083
2141
  if (v?.id != null &&
2084
2142
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
2085
2143
  isUnsecuredPortableObject(this) ||
2086
- (isInPortableChain(this) && isCompatibleEf61Iri(v.id))) &&
2144
+ mustDereferencePortableObject(
2145
+ this, ${trustOwner}, v.id, options,
2146
+ )) &&
2087
2147
  !this.${await getFieldName(property.uri, "#_trust")}.has(i)) {
2088
2148
  if (options.crossOrigin === "throw") {
2089
2149
  throw new Error(
@@ -2128,13 +2188,19 @@ const INTERNAL_RUNTIME_IMPORTS = [
2128
2188
  ].join(",\n ");
2129
2189
  const PORTABLE_DEREFERENCE_IMPORTS = [
2130
2190
  "copyPortableProvenance",
2191
+ "createSnapshotContextLoader",
2131
2192
  "dereferencePortableIri",
2132
- "isCompatibleEf61Iri",
2133
- "isInPortableChain",
2193
+ "getPortableResponseClaim",
2134
2194
  "isPortableIri",
2195
+ "isPortableMode",
2135
2196
  "isUnsecuredPortableObject",
2197
+ "isUnverifiedPortableClaim",
2198
+ "markUnverifiedPortableClaim",
2199
+ "mustDereferencePortableObject",
2200
+ "parseCompatibleEf61Reference",
2201
+ "type PortableResponseClaim",
2136
2202
  "recordPortableReferrer",
2137
- "rejectPortableChainReference",
2203
+ "rejectMalformedCompatibleReference",
2138
2204
  "warnUnverifiableEmbeddedObject"
2139
2205
  ].join(",\n ");
2140
2206
  const SIGNED_REPRESENTATION_IMPORTS = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-tools",
3
- "version": "2.4.0-dev.2063+366c0362",
3
+ "version": "2.4.0-dev.2071+8b9dccb9",
4
4
  "description": "Code generator for Activity Vocabulary APIs",
5
5
  "homepage": "https://fedify.dev/",
6
6
  "repository": {