@fedify/fedify 2.4.0-dev.2141 → 2.4.0-dev.2155

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 (85) hide show
  1. package/dist/{builder-BI7H61zO.mjs → builder-CxHALSwA.mjs} +56 -3
  2. package/dist/compat/mod.d.cts +1 -1
  3. package/dist/compat/mod.d.ts +1 -1
  4. package/dist/compat/transformers.test.mjs +1 -1
  5. package/dist/{compound-proof-D0H4LLvQ.mjs → compound-proof-nhrXTRQO.mjs} +216 -4
  6. package/dist/{context-CrDDVrbF.d.cts → context-BMggDR-l.d.cts} +394 -5
  7. package/dist/{context-DfSVPcJ8.mjs → context-OrnjnuMq.mjs} +8 -1
  8. package/dist/{context-B2C8nuN3.d.ts → context-exYu7gDU.d.ts} +394 -5
  9. package/dist/{deno-BXI_BLNy.mjs → deno-YLLbRq06.mjs} +1 -1
  10. package/dist/{docloader-B5BIo7e9.mjs → docloader-vc-pSu9-.mjs} +2 -2
  11. package/dist/federation/builder.test.mjs +1 -1
  12. package/dist/federation/compound-fanout.test.mjs +3 -3
  13. package/dist/federation/handler-compound-proof.test.mjs +4 -4
  14. package/dist/federation/handler.test.mjs +6 -6
  15. package/dist/federation/hashlink-media.test.mjs +2 -2
  16. package/dist/federation/idempotency.test.mjs +2 -2
  17. package/dist/federation/metrics.test.mjs +1 -1
  18. package/dist/federation/middleware.test.mjs +8 -8
  19. package/dist/federation/mod.cjs +1 -1
  20. package/dist/federation/mod.d.cts +3 -3
  21. package/dist/federation/mod.d.ts +3 -3
  22. package/dist/federation/mod.js +1 -1
  23. package/dist/federation/outgoing-proof.test.mjs +5 -5
  24. package/dist/federation/portable-actor.test.mjs +3 -3
  25. package/dist/federation/portable-chain.test.mjs +3 -3
  26. package/dist/federation/portable-collection.test.d.mts +2 -0
  27. package/dist/federation/portable-collection.test.mjs +768 -0
  28. package/dist/federation/portable-gateway-keys.test.mjs +4 -4
  29. package/dist/federation/portable-inbox.test.mjs +4 -4
  30. package/dist/federation/portable.test.mjs +4 -4
  31. package/dist/federation/send.test.mjs +3 -3
  32. package/dist/federation/tasks/enqueue.test.mjs +2 -2
  33. package/dist/federation/tasks/tasks.test.mjs +3 -3
  34. package/dist/federation/temporal.test.mjs +1 -1
  35. package/dist/federation/webfinger.test.mjs +2 -2
  36. package/dist/{federation-DqDOPjWo.cjs → federation-D9TufmIO.cjs} +684 -68
  37. package/dist/{http-CEx2SZjf.mjs → http-CXnNbRe_.mjs} +4 -4
  38. package/dist/{http-D4KW2GTi.js → http-Dk4O3WM0.js} +7 -2
  39. package/dist/{http-DSYQQn23.cjs → http-eqYXHRkz.cjs} +12 -1
  40. package/dist/{key-C0giKuki.mjs → key-BZ-Z4uez.mjs} +2 -2
  41. package/dist/{kv-cache-D_E-2K3i.js → kv-cache-3uKc0G76.js} +1 -1
  42. package/dist/{kv-cache-AWTrxTq3.mjs → kv-cache-DZr8HTel.mjs} +1 -1
  43. package/dist/{kv-cache-BcsvaCCL.cjs → kv-cache-DzClEalR.cjs} +1 -1
  44. package/dist/{ld-CWDReGMZ.mjs → ld-Djxsq6JR.mjs} +3 -3
  45. package/dist/{metrics-DxlVXwn5.mjs → metrics-CBHhbHgG.mjs} +1 -1
  46. package/dist/{middleware-1mv9QR16.js → middleware-BDUR99k3.js} +686 -70
  47. package/dist/{middleware-B7stx5gy.mjs → middleware-BahNnLfD.mjs} +1 -1
  48. package/dist/{middleware-CAWRGSwH.mjs → middleware-DDa8pCUa.mjs} +431 -80
  49. package/dist/{mod-C06GoL5Z.d.ts → mod-CnGtADvO.d.ts} +1 -1
  50. package/dist/{mod-B7SfEqIP.d.cts → mod-Decmur1U.d.cts} +1 -1
  51. package/dist/mod.cjs +4 -4
  52. package/dist/mod.d.cts +4 -4
  53. package/dist/mod.d.ts +4 -4
  54. package/dist/mod.js +4 -4
  55. package/dist/nodeinfo/handler.test.mjs +2 -2
  56. package/dist/{owner-CgoCOTUQ.mjs → owner-OdWSE8am.mjs} +3 -3
  57. package/dist/{portable-collection-CG9P_i0E.js → portable-collection-BCy06GiS.js} +1 -1
  58. package/dist/{portable-collection-0_5DyXMt.mjs → portable-collection-DAV7Ho3m.mjs} +2 -2
  59. package/dist/{portable-collection-BD8fE3j3.cjs → portable-collection-wBWbuHOH.cjs} +1 -1
  60. package/dist/{portable-key-BXkgMpw1.mjs → portable-key-BL6K88p2.mjs} +1 -1
  61. package/dist/{proof-B5s-W6Sm.mjs → proof-vZ04IAjq.mjs} +10 -5
  62. package/dist/{send-BAJvkdNL.mjs → send-ylV8KCLx.mjs} +3 -3
  63. package/dist/sig/compound-proof-discovery.test.mjs +1 -1
  64. package/dist/sig/compound-proof-producer.test.mjs +1 -1
  65. package/dist/sig/compound-proof-verification.test.mjs +2 -2
  66. package/dist/sig/compound-proof.test.mjs +2 -2
  67. package/dist/sig/http.test.mjs +2 -2
  68. package/dist/sig/key.test.mjs +1 -1
  69. package/dist/sig/ld.test.mjs +2 -2
  70. package/dist/sig/mod.cjs +2 -2
  71. package/dist/sig/mod.js +2 -2
  72. package/dist/sig/owner.test.mjs +1 -1
  73. package/dist/sig/portable-collection.test.mjs +1 -1
  74. package/dist/sig/portable-key.test.mjs +5 -5
  75. package/dist/sig/proof.test.mjs +3 -3
  76. package/dist/{temporal-BkCPJ_uC.mjs → temporal-BTD4f_mZ.mjs} +1 -1
  77. package/dist/testing/kv.test.mjs +1 -1
  78. package/dist/testing/mod.d.mts +393 -4
  79. package/dist/testing/mod.mjs +2 -2
  80. package/dist/{testing-otQhu4aD.mjs → testing-CKaJhcA0.mjs} +1 -1
  81. package/dist/utils/docloader.test.mjs +2 -2
  82. package/dist/utils/kv-cache.test.mjs +1 -1
  83. package/dist/utils/mod.cjs +1 -1
  84. package/dist/utils/mod.js +1 -1
  85. package/package.json +6 -6
@@ -1,8 +1,8 @@
1
1
  import "temporal-polyfill";
2
2
  import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
- import { n as version, t as name } from "./deno-BXI_BLNy.mjs";
5
- import { c as isPortableId } from "./portable-key-id-Bg259c4Z.mjs";
4
+ import { n as version, t as name } from "./deno-YLLbRq06.mjs";
5
+ import { c as isPortableId, r as getPortableDid, t as getCanonicalPortableId } from "./portable-key-id-Bg259c4Z.mjs";
6
6
  import { t as ActivityListenerSet } from "./activity-listener-C-BSbKI7.mjs";
7
7
  import { getLogger } from "@logtape/logtape";
8
8
  import { Router, RouterError, assertPath } from "@fedify/uri-template";
@@ -89,7 +89,7 @@ var FederationBuilderImpl = class {
89
89
  * specified.
90
90
  */
91
91
  async build(options) {
92
- const { FederationImpl } = await import("./middleware-B7stx5gy.mjs");
92
+ const { FederationImpl } = await import("./middleware-BahNnLfD.mjs");
93
93
  const f = new FederationImpl(options);
94
94
  const trailingSlashInsensitiveValue = f.router.trailingSlashInsensitive;
95
95
  f.router = this.router.clone();
@@ -166,6 +166,7 @@ var FederationBuilderImpl = class {
166
166
  else if (!portable && actor.id.href != context.getActorUri(identifier).href) logger.warn("Actor dispatcher returned an actor with an id property that does not match the actor URI. Set the property with Context.getActorUri(identifier).");
167
167
  if (actor instanceof Tombstone) return actor;
168
168
  if (actor.id != null && isCompatibleEf61Iri(actor.id)) warnCompatibleActorId(actor.id, actor.gateway);
169
+ if (portable) this.#warnPortableCollectionIds(context, identifier, actor);
169
170
  if (this.followingCallbacks != null && this.followingCallbacks.dispatcher != null) {
170
171
  if (actor.followingId == null) logger.warn("You configured a following collection dispatcher, but the actor does not have a following property. Set the property with Context.getFollowingUri(identifier).");
171
172
  else if (!portable && actor.followingId.href != context.getFollowingUri(identifier).href) logger.warn("You configured a following collection dispatcher, but the actor's following property does not match the following collection URI. Set the property with Context.getFollowingUri(identifier).");
@@ -651,6 +652,10 @@ var FederationBuilderImpl = class {
651
652
  authorize(predicate) {
652
653
  callbacks.authorizePredicate = predicate;
653
654
  return setters;
655
+ },
656
+ mapPortableOwner(mapper) {
657
+ callbacks.portableOwnerMapper = mapper;
658
+ return setters;
654
659
  }
655
660
  };
656
661
  return setters;
@@ -672,6 +677,54 @@ var FederationBuilderImpl = class {
672
677
  this.outboxPermanentFailureHandler = handler;
673
678
  }
674
679
  /**
680
+ * Warns if a portable actor's collection properties that are portable IDs
681
+ * or compatible identifiers do not refer to the collections that
682
+ * the registered collection dispatchers serve through the FEP-ef61 gateway
683
+ * endpoint for the actor's DID. Properties with ordinary HTTP(S) URLs are
684
+ * not compared, since a portable actor may keep ordinary collections.
685
+ */
686
+ #warnPortableCollectionIds(context, identifier, actor) {
687
+ const did = actor.id == null ? null : getPortableDid(actor.id);
688
+ if (did == null) return;
689
+ const logger = getLogger([
690
+ "fedify",
691
+ "federation",
692
+ "actor"
693
+ ]);
694
+ const check = (registered, property, value, helper, build) => {
695
+ if (!registered || value == null || !isPortableId(value)) return;
696
+ const actual = getCanonicalPortableId(value);
697
+ if (actual == null) {
698
+ logger.warn("The actor's {property} property, {value}, is a malformed FEP-ef61 portable ID or compatible identifier.", {
699
+ property,
700
+ value: value.href
701
+ });
702
+ return;
703
+ }
704
+ let expected;
705
+ try {
706
+ expected = build();
707
+ } catch (error) {
708
+ if (error instanceof TypeError || error instanceof RouterError) return;
709
+ throw error;
710
+ }
711
+ if (actual === getCanonicalPortableId(expected)) return;
712
+ logger.warn("The portable actor's {property} property, {value}, does not match the portable ID of the collection that the gateway endpoint serves, {expected}. Set the property with Context.{helper}(identifier, did).", {
713
+ property,
714
+ value: value.href,
715
+ expected: expected.href,
716
+ helper
717
+ });
718
+ };
719
+ check(this.outboxCallbacks?.dispatcher != null, "outbox", actor.outboxId, "getPortableOutboxUri", () => context.getPortableOutboxUri(identifier, did));
720
+ check(this.inboxCallbacks?.dispatcher != null || this.router.has("inbox"), "inbox", actor.inboxId, "getPortableInboxUri", () => context.getPortableInboxUri(identifier, did));
721
+ check(this.followingCallbacks?.dispatcher != null, "following", actor.followingId, "getPortableFollowingUri", () => context.getPortableFollowingUri(identifier, did));
722
+ check(this.followersCallbacks?.dispatcher != null, "followers", actor.followersId, "getPortableFollowersUri", () => context.getPortableFollowersUri(identifier, did));
723
+ check(this.likedCallbacks?.dispatcher != null, "liked", actor.likedId, "getPortableLikedUri", () => context.getPortableLikedUri(identifier, did));
724
+ check(this.featuredCallbacks?.dispatcher != null, "featured", actor.featuredId, "getPortableFeaturedUri", () => context.getPortableFeaturedUri(identifier, did));
725
+ check(this.featuredTagsCallbacks?.dispatcher != null, "featuredTags", actor.featuredTagsId, "getPortableFeaturedTagsUri", () => context.getPortableFeaturedTagsUri(identifier, did));
726
+ }
727
+ /**
675
728
  * Converts a name (string or symbol) to a unique string identifier.
676
729
  * For symbols, generates and caches a UUID if not already present.
677
730
  * For strings, returns the string as-is.
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Zt as ActivityTransformer, n as Context } from "../context-CrDDVrbF.cjs";
2
+ import { Qt as ActivityTransformer, n as Context } from "../context-BMggDR-l.cjs";
3
3
  import { Activity } from "@fedify/vocab";
4
4
 
5
5
  //#region src/compat/transformers.d.ts
@@ -1,5 +1,5 @@
1
1
  /// <reference lib="esnext.temporal" />
2
- import { Zt as ActivityTransformer, n as Context } from "../context-B2C8nuN3.js";
2
+ import { Qt as ActivityTransformer, n as Context } from "../context-exYu7gDU.js";
3
3
  import { Activity } from "@fedify/vocab";
4
4
 
5
5
  //#region src/compat/transformers.d.ts
@@ -5,7 +5,7 @@ import { t as MemoryKvStore } from "../kv-DCHkaJ9-.mjs";
5
5
  import { t as assertEquals } from "../assert_equals-Z6IcEbWU.mjs";
6
6
  import { t as assertInstanceOf } from "../assert_instance_of-mrXWWNY-.mjs";
7
7
  import { t as assert } from "../assert-D1Eafmd_.mjs";
8
- import { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-CAWRGSwH.mjs";
8
+ import { E as autoIdAssigner, T as actorDehydrator, n as FederationImpl } from "../middleware-DDa8pCUa.mjs";
9
9
  import { Follow, Person } from "@fedify/vocab";
10
10
  import { test } from "@fedify/fixture";
11
11
  //#region src/compat/transformers.test.ts
@@ -3,9 +3,9 @@ import "urlpattern-polyfill";
3
3
  globalThis.addEventListener = () => {};
4
4
  import { c as isPortableId, i as getRawCanonicalPortableId, t as getCanonicalPortableId } from "./portable-key-id-Bg259c4Z.mjs";
5
5
  import { n as preloadedOnlyDocumentLoader } from "./public-audience--klBIOk1.mjs";
6
- import { c as getNormalizationContextLoader } from "./ld-CWDReGMZ.mjs";
7
- import { a as verifyMapLocalProof, c as verifyPortableObjectProofPolicy } from "./proof-B5s-W6Sm.mjs";
8
- import { parseIri } from "@fedify/vocab-runtime";
6
+ import { c as getNormalizationContextLoader } from "./ld-Djxsq6JR.mjs";
7
+ import { l as verifyPortableObjectProofPolicy, n as classifyFep2277CoreType, o as verifyMapLocalProof } from "./proof-vZ04IAjq.mjs";
8
+ import { parseIri, preloadedContexts } from "@fedify/vocab-runtime";
9
9
  import jsonld from "@fedify/vocab-runtime/jsonld";
10
10
  //#region src/sig/compound-proof.ts
11
11
  const textEncoder = new TextEncoder();
@@ -736,5 +736,217 @@ function isSingleStringValue(values, datatype) {
736
736
  const keys = Object.keys(value);
737
737
  return keys.length === 1 || datatype != null && keys.length === 2 && value["@type"] === datatype;
738
738
  }
739
+ /**
740
+ * FEP-2277 core types that FEP-ef61 does not require to carry proofs.
741
+ */
742
+ const UNSECURED_CORE_TYPES = /* @__PURE__ */ new Set([
743
+ "collection",
744
+ "link",
745
+ "verificationMethod",
746
+ "publicKey"
747
+ ]);
748
+ /**
749
+ * Applies the FEP-ef61 proof policy, under the map-local compound-proof
750
+ * profile, to every portable object embedded in a document that a gateway is
751
+ * about to serve, e.g., the items of a portable collection page. The root
752
+ * map itself is not checked, as the caller built it.
753
+ *
754
+ * Each map below the root whose direct `id` or `@id` is a portable ID or
755
+ * a compatible identifier is checked independently of the others:
756
+ *
757
+ * - A map with a direct `proof` is a separately secured document: the proof
758
+ * has to be a single map, the map has to carry its own `@context`, and
759
+ * the proof has to verify over the map exactly as it is served, with only
760
+ * its own proof removed, and be made with a key of the DID in the map's
761
+ * ID, as the map-local compound-proof profile requires.
762
+ * - A map without a proof has to be a collection, a link, or a key, which
763
+ * FEP-ef61 does not require to be secured. It is classified under its
764
+ * effective context, i.e., the `@context` values of its ancestors and
765
+ * itself, which therefore may only use the simple, preloaded contexts
766
+ * that the compound-proof policy accepts.
767
+ *
768
+ * Maps that merely refer to a portable object, i.e., have no member other
769
+ * than `id` or `@id`, and maps with non-portable IDs, are neither checked nor
770
+ * verified. Every `@context` in the document, however, has to be simple, and
771
+ * every portable object that the expanded document describes has to be
772
+ * a map found this way, so that no context can hide a portable object from
773
+ * this check, e.g., by aliasing `@id` or redefining `proof`. The input must be a finite, already-materialized JSON tree, such
774
+ * as the compact JSON-LD document that is about to be served.
775
+ *
776
+ * @param json The document to check.
777
+ * @param options The options for verifying the proofs. Proofs whose
778
+ * verification methods are not `did:key` DID URLs may make
779
+ * the document loader fetch DID documents.
780
+ * @returns The result, which names the first refused map, if any.
781
+ * @internal
782
+ */
783
+ async function verifyServedPortableObjects(json, options = {}) {
784
+ json = JSON.parse(JSON.stringify(json));
785
+ const collected = collectServedPortableMaps(json);
786
+ if (!("maps" in collected)) return collected;
787
+ const maps = collected.maps;
788
+ const discovered = /* @__PURE__ */ new Map();
789
+ const ids = maps.map((candidate) => candidate.id);
790
+ const rootId = isJsonMap(json) ? [json.id, json["@id"]].find(isPortableIdValue) : void 0;
791
+ if (rootId != null) ids.push(rootId);
792
+ for (const id of ids) discovered.set(id, (discovered.get(id) ?? 0) + 1);
793
+ let hidden;
794
+ try {
795
+ hidden = findHiddenPortableObject(await jsonld.expand(json, { documentLoader: preloadedOnlyDocumentLoader }), discovered);
796
+ } catch {
797
+ return {
798
+ verified: false,
799
+ path: "",
800
+ id: "",
801
+ reason: "unsupportedContext"
802
+ };
803
+ }
804
+ if (hidden != null) return {
805
+ verified: false,
806
+ path: "",
807
+ id: hidden,
808
+ reason: "hiddenPortableObject"
809
+ };
810
+ for (const candidate of maps) {
811
+ const reason = await checkServedPortableMap(candidate, options);
812
+ if (reason != null) return {
813
+ verified: false,
814
+ path: candidate.path,
815
+ id: candidate.id,
816
+ reason
817
+ };
818
+ }
819
+ return { verified: true };
820
+ }
821
+ /**
822
+ * Finds a portable object that an expanded JSON-LD document describes, i.e.,
823
+ * a node with a portable `@id` and other members, more times than the given
824
+ * numbers of maps found for its ID.
825
+ */
826
+ function findHiddenPortableObject(expanded, discovered) {
827
+ const remaining = new Map(discovered);
828
+ const pending = [expanded];
829
+ while (pending.length > 0) {
830
+ const value = pending.pop();
831
+ if (Array.isArray(value)) {
832
+ pending.push(...value);
833
+ continue;
834
+ }
835
+ if (!isJsonMap(value)) continue;
836
+ const id = value["@id"];
837
+ if (isPortableIdValue(id) && Object.keys(value).some((key) => key !== "@id")) {
838
+ const count = remaining.get(id) ?? 0;
839
+ if (count < 1) return id;
840
+ remaining.set(id, count - 1);
841
+ }
842
+ pending.push(...Object.values(value));
843
+ }
844
+ }
845
+ /**
846
+ * Checks whether a context uses only preloaded remote contexts and simple
847
+ * term definitions, so that the context in effect for a map can be told from
848
+ * the contexts of its ancestors.
849
+ */
850
+ function isCheckableContext(context) {
851
+ return (Array.isArray(context) ? context : [context]).every((value) => typeof value === "string" ? Object.hasOwn(preloadedContexts, value) : !Array.isArray(value) && isSimpleContext(value));
852
+ }
853
+ /**
854
+ * Checks whether every remote context that a context refers to is preloaded,
855
+ * so that all of its definitions are known.
856
+ */
857
+ function hasOnlyPreloadedRemoteContexts(context) {
858
+ return (Array.isArray(context) ? context : [context]).every((value) => typeof value === "string" ? Object.hasOwn(preloadedContexts, value) : !Array.isArray(value));
859
+ }
860
+ /**
861
+ * Checks whether a map or any map below it, outside proof and context values,
862
+ * has a portable `id` or `@id` and other members.
863
+ */
864
+ function hasLiteralPortableObject(json) {
865
+ return findInJsonMaps(json, (map) => [map.id, map["@id"]].some(isPortableIdValue) && Object.keys(map).some((key) => key !== "id" && key !== "@id") ? true : void 0) ?? false;
866
+ }
867
+ function collectServedPortableMaps(json) {
868
+ const maps = [];
869
+ const seen = /* @__PURE__ */ new Set();
870
+ const pending = [{
871
+ value: json,
872
+ path: "",
873
+ depth: 0,
874
+ contexts: []
875
+ }];
876
+ while (pending.length > 0) {
877
+ const { value, path, depth, contexts } = pending.pop();
878
+ if (typeof value !== "object" || value == null || seen.has(value)) continue;
879
+ seen.add(value);
880
+ if (Array.isArray(value)) {
881
+ for (let index = value.length - 1; index >= 0; index--) pending.push({
882
+ value: value[index],
883
+ path: childPath(path, String(index)),
884
+ depth: depth + 1,
885
+ contexts
886
+ });
887
+ continue;
888
+ }
889
+ const map = value;
890
+ const hasContext = Object.hasOwn(map, "@context");
891
+ if (hasContext && !isCheckableContext(map["@context"])) {
892
+ if (hasOnlyPreloadedRemoteContexts(map["@context"]) && !hasLiteralPortableObject(map)) continue;
893
+ const id = [map.id, map["@id"]].find((v) => typeof v === "string");
894
+ return {
895
+ verified: false,
896
+ path,
897
+ id: typeof id === "string" ? id : "",
898
+ reason: "unsupportedContext"
899
+ };
900
+ }
901
+ const mapContexts = hasContext ? [...contexts, map["@context"]] : contexts;
902
+ const id = [map.id, map["@id"]].find(isPortableIdValue);
903
+ if (depth > 0 && id != null && Object.keys(map).some((key) => key !== "id" && key !== "@id")) maps.push({
904
+ path,
905
+ id,
906
+ map,
907
+ contexts: mapContexts
908
+ });
909
+ const keys = Object.keys(map);
910
+ for (let index = keys.length - 1; index >= 0; index--) {
911
+ const key = keys[index];
912
+ if (key === "proof" || key === "@context") continue;
913
+ pending.push({
914
+ value: map[key],
915
+ path: childPath(path, key),
916
+ depth: depth + 1,
917
+ contexts: mapContexts
918
+ });
919
+ }
920
+ }
921
+ maps.sort((left, right) => comparePaths(left.path, right.path));
922
+ return { maps };
923
+ }
924
+ async function checkServedPortableMap({ map, contexts }, options) {
925
+ if (Object.hasOwn(map, "proof")) {
926
+ if (!isJsonMap(map.proof)) return "unsupportedProofShape";
927
+ if (!Object.hasOwn(map, "@context")) return "missingContext";
928
+ try {
929
+ const policy = await verifyPortableObjectProofPolicy(map, await verifyMapLocalProof(map, options), options);
930
+ return policy.verified ? null : policy.reason.type;
931
+ } catch (error) {
932
+ if (error instanceof TypeError) return "invalidPortableObject";
933
+ throw error;
934
+ }
935
+ }
936
+ const flattened = contexts.flatMap((context) => Array.isArray(context) ? context : [context]);
937
+ if (flattened.length < 1 || !isSimpleContext(flattened)) return "unsupportedContext";
938
+ let expanded;
939
+ try {
940
+ expanded = await jsonld.expand({
941
+ ...map,
942
+ "@context": flattened
943
+ }, { documentLoader: preloadedOnlyDocumentLoader });
944
+ } catch {
945
+ return "unsupportedContext";
946
+ }
947
+ if (expanded.length !== 1 || !isJsonMap(expanded[0])) return "invalidPortableObject";
948
+ const type = classifyFep2277CoreType(expanded[0]);
949
+ return UNSECURED_CORE_TYPES.has(type) ? null : "missingProof";
950
+ }
739
951
  //#endregion
740
- export { verifyCompoundPortableObjectProofs as a, inspectCompoundPortableObjectApplicability as i, discoverCompoundProofDocuments as n, verifyCompoundProofDocuments as o, findUnsupportedCompoundProofShape as r, containsCompoundPortableObject as t };
952
+ export { verifyCompoundPortableObjectProofs as a, inspectCompoundPortableObjectApplicability as i, discoverCompoundProofDocuments as n, verifyCompoundProofDocuments as o, findUnsupportedCompoundProofShape as r, verifyServedPortableObjects as s, containsCompoundPortableObject as t };