Repository: apollographql/apollo-server
Pull request #7136 (2022-11-09 22:35:34)

Fix error reporting when trace data is not included
This is a 2-part change which requires an update to the gateway runtime as well. Related PR: https://github.com/apollographql/federation/pull/2242

It was brought to our attention that trace information w.r.t. subgraph errors is incorrect in the case that there is no trace in the subgraph response (i.e. no ftv1 support in the subgraph or `fieldLevelInstrumentation` is 0 or returns 0).

With this change:
* Errors reported by subgraphs (with no trace data in the response) are now accurately reflected in the numeric error stats
* Operations that receive errors from subgraphs (with no trace data in the response) are no longer sent as incomplete, error-less traces

The gateway change now collects errors separately when no trace data is found and passes that error information (subgraph and error path) along with the other metrics data for the plugin to consume. The plugin uses the subgraph name and error path in order to add error stat information to the tree.
<!--
First, 🌠 thank you 🌠 for taking the time to consider a contribution to Apollo!

Here are some important details to follow:

* ⏰ Your time is important
          To save your precious time, if the contribution you are making will take more
          than an hour, please make sure it has been discussed in an issue first.
          This is especially true for feature requests!
* 💡 Features
          Feature requests can be created and discussed within a GitHub Issue.  Be
          sure to search for existing feature requests (and related issues!) prior to
          opening a new request.  If an existing issue covers the need, please upvote
          that issue by using the 👍 emote, rather than opening a new issue.
* 🔌 Integrations
          Apollo Server has many web-framework integrations including Express, Koa,
          Hapi and more.  When adding a new feature, or fixing a bug, please take a
          peak and see if other integrations are also affected.  In most cases, the
          fix can be applied to the other frameworks as well.  Please note that,
          since new web-frameworks have a high maintenance cost, pull-requests for
          new web-frameworks should be discussed with a project maintainer first.
* 🕷 Bug fixes
          These can be created and discussed in this repository. When fixing a bug,
          please _try_ to add a test which verifies the fix.  If you cannot, you should
          still submit the PR but we may still ask you (and help you!) to create a test.
* 📖 Contribution guidelines
          Follow https://github.com/apollographql/apollo-server/blob/main/CONTRIBUTING.md
          when submitting a pull request.  Make sure existing tests still pass, and add
          tests for all new behavior.
* ✏️ Explain your pull request
          Describe the big picture of your changes here to communicate to what your
          pull request is meant to accomplish.  Provide 🔗 links 🔗 to associated issues!

We hope you will find this to be a positive experience!  Open source contribution can be intimidating and we hope to alleviate that pain as much as possible.  Without following these guidelines, you may be missing context that can help you succeed with your contribution, which is why we encourage discussion first.  Ultimately, there is no guarantee that we will be able to merge your pull-request, but by following these guidelines we can try to avoid disappointment.
-->


netlify[bot]: ### <span aria-hidden="true">👷</span> Deploy Preview for *apollo-server-docs* processing.


|  Name | Link |
|---------------------------------|------------------------|
|<span aria-hidden="true">🔨</span> Latest commit | 933be1d532af98a186e8c7d1079982d4e32f20dc |
|<span aria-hidden="true">🔍</span> Latest deploy log | https://app.netlify.com/sites/apollo-server-docs/deploys/636c2b3801af7c0007757742 |
codesandbox-ci[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/apollographql/apollo-server/pr/7136/builds/314344) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 933be1d532af98a186e8c7d1079982d4e32f20dc:

|Sandbox| Source |
|--|--|
|[Apollo Server Typescript](https://codesandbox.io/s/apollo-server-typescript-ei3ivt)| Configuration |
|[Apollo Server](https://codesandbox.io/s/apollo-server-gh2nln)| Configuration |


Patch:
diff --git a/.changeset/heavy-poets-wink.md b/.changeset/heavy-poets-wink.md
new file mode 100644
index 000000000..f0c84d808
--- /dev/null
+++ b/.changeset/heavy-poets-wink.md
@@ -0,0 +1,9 @@
+---
+'@apollo/server': patch
+---
+
+Errors reported by subgraphs (with no trace data in the response) are now accurately reflected in the numeric error stats.
+
+Operations that receive errors from subgraphs (with no trace data in the response) are no longer sent as incomplete, error-less traces.
+
+Note: in order for this fix to take effect, your `@apollo/gateway` version must be updated to v2.3.1 or later.
diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml
index 3756e8e8f..dcf8c7d6c 100644
--- a/.github/workflows/release-pr.yml
+++ b/.github/workflows/release-pr.yml
@@ -9,6 +9,7 @@ jobs:
   release:
     name: Release
     runs-on: ubuntu-latest
+    if: github.repository == 'apollographql/apollo-server'
     steps:
       - name: Checkout Repo
         uses: actions/checkout@v3
diff --git a/docs/source/data/fetching-rest.mdx b/docs/source/data/fetching-rest.mdx
index 6f184f927..f2dc5c35e 100644
--- a/docs/source/data/fetching-rest.mdx
+++ b/docs/source/data/fetching-rest.mdx
@@ -416,7 +416,7 @@ class PersonalizationAPI extends RESTDataSource {
   }
 
   // highlight-start
-  override willSendRequest(request: AugmentedRequest) {
+  override willSendRequest(_path: string, request: AugmentedRequest) {
     request.headers['authorization'] = this.token;
   }
   // highlight-end
@@ -446,7 +446,7 @@ class PersonalizationAPI extends RESTDataSource {
   }
 
   // highlight-start
-  override willSendRequest(request: AugmentedRequest) {
+  override willSendRequest(_path: string, request: AugmentedRequest) {
     request.params.set('api_key', this.token);
   }
   // highlight-end
@@ -522,7 +522,7 @@ class PersonalizationAPI extends RESTDataSource {
     this.token = options.token;
   }
 
-  override willSendRequest(request: AugmentedRequest) {
+  override willSendRequest(_path: string, request: AugmentedRequest) {
     request.headers['authorization'] = this.token;
   }
 
diff --git a/docs/source/schema/custom-scalars.mdx b/docs/source/schema/custom-scalars.mdx
index 21061a8a5..fede86a49 100644
--- a/docs/source/schema/custom-scalars.mdx
+++ b/docs/source/schema/custom-scalars.mdx
@@ -45,11 +45,17 @@ import { GraphQLScalarType, Kind } from 'graphql';
 const dateScalar = new GraphQLScalarType({
   name: 'Date',
   description: 'Date custom scalar type',
-  serialize(value: Date) {
-    return value.getTime(); // Convert outgoing Date to integer for JSON
+  serialize(value) {
+    if (value instanceof Date) {
+      return value.getTime(); // Convert outgoing Date to integer for JSON
+    }
+    throw Error('GraphQL Date Scalar serializer expected a `Date` object');
   },
-  parseValue(value: number) {
-    return new Date(value); // Convert incoming integer to Date
+  parseValue(value) {
+    if (typeof value === 'number') {
+      return new Date(value); // Convert incoming integer to Date
+    }
+    throw new Error('GraphQL Date Scalar parser expected a `number`');
   },
   parseLiteral(ast) {
     if (ast.kind === Kind.INT) {
diff --git a/package-lock.json b/package-lock.json
index e30ce0331..e42b83c4f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,9 @@
       ],
       "devDependencies": {
         "@apollo/client": "3.7.7",
+        "@apollo/gateway": "2.3.1",
         "@apollo/server-plugin-landing-page-graphql-playground": "4.0.0",
+        "@apollo/subgraph": "2.3.1",
         "@apollo/utils.createhash": "2.0.0",
         "@changesets/changelog-github": "0.4.8",
         "@changesets/cli": "2.26.0",
@@ -146,6 +148,107 @@
         "node": ">=8"
       }
     },
+    "node_modules/@apollo/composition": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/composition/-/composition-2.3.1.tgz",
+      "integrity": "sha512-lNPBGkNTcWhEHFLjlWAr/ViqpMNOj+BxDPSktqp/Pd1dxWOzUuDLHSGjJY4ESKrBE2RhQ9Nb3jIKbsLmjF6jNg==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-graphs": "2.3.1"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
+    "node_modules/@apollo/federation-internals": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/federation-internals/-/federation-internals-2.3.1.tgz",
+      "integrity": "sha512-XLsXLeEFBGZ5lhj4huEJTP5TAq3+t+EXqoFAEFX8hSQMAJ+lW+w51YZMbB4R7naojFf1ehlHSAit523GTE9aMA==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "js-levenshtein": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
+    "node_modules/@apollo/gateway": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/gateway/-/gateway-2.3.1.tgz",
+      "integrity": "sha512-kkZP591To697XL8rH6JOvStOU7URcHInKWEU2q3Llimwt4Gm1mlshlNNnlRiHy2ri6tim0/wL1qLBtFG2LUfDQ==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/composition": "2.3.1",
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-planner": "2.3.1",
+        "@apollo/server-gateway-interface": "^1.1.0",
+        "@apollo/usage-reporting-protobuf": "^4.0.0",
+        "@apollo/utils.createhash": "^1.1.0",
+        "@apollo/utils.fetcher": "^1.1.0",
+        "@apollo/utils.isnodelike": "^1.1.0",
+        "@apollo/utils.logger": "^1.0.0",
+        "@josephg/resolvable": "^1.0.1",
+        "@opentelemetry/api": "^1.0.1",
+        "@types/node-fetch": "^2.6.2",
+        "async-retry": "^1.3.3",
+        "loglevel": "^1.6.1",
+        "lru-cache": "^7.13.1",
+        "make-fetch-happen": "^11.0.0",
+        "node-abort-controller": "^3.0.1",
+        "node-fetch": "^2.6.7"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
+    "node_modules/@apollo/gateway/node_modules/@apollo/utils.createhash": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-1.1.0.tgz",
+      "integrity": "sha512-5fT4ZiW75515OlikWpIQzaVDws1yy9VgYSoHoJCrvI2UH6/7YNKXQjbjT5qVYu6ytch2wBxFMfFfYWMn/2bSCQ==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/utils.isnodelike": "^1.1.0",
+        "sha.js": "^2.4.11"
+      },
+      "engines": {
+        "node": ">=12.13.0"
+      }
+    },
+    "node_modules/@apollo/gateway/node_modules/@apollo/utils.isnodelike": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-1.1.0.tgz",
+      "integrity": "sha512-q/Q82kBUSEcx1ED11JO1TYBY781mWluUnBD8NvhjHVsu1K1C5R9BZVUxShyK/V8XcePcRUB5fdWOcBMGwS0KOA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.13.0"
+      }
+    },
+    "node_modules/@apollo/gateway/node_modules/@apollo/utils.logger": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.1.tgz",
+      "integrity": "sha512-XdlzoY7fYNK4OIcvMD2G94RoFZbzTQaNP0jozmqqMudmaGo2I/2Jx71xlDJ801mWA/mbYRihyaw6KJii7k5RVA==",
+      "dev": true
+    },
+    "node_modules/@apollo/gateway/node_modules/lru-cache": {
+      "version": "7.14.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+      "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/@apollo/protobufjs": {
       "version": "1.2.7",
       "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.7.tgz",
@@ -170,6 +273,59 @@
         "apollo-pbts": "bin/pbts"
       }
     },
+    "node_modules/@apollo/query-graphs": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-graphs/-/query-graphs-2.3.1.tgz",
+      "integrity": "sha512-mvEBk3KTrKr5Av3KlwPG+1Ve8vPngNxLb0NSc49FHGEticpd/p8ZV6hD2Jh8LNLdhEu5g0POr78b+mtJccqo4g==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/federation-internals": "2.3.1",
+        "@types/uuid": "^8.3.4",
+        "deep-equal": "^2.0.5",
+        "ts-graphviz": "^0.16.0",
+        "uuid": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
+    "node_modules/@apollo/query-graphs/node_modules/@types/uuid": {
+      "version": "8.3.4",
+      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+      "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
+      "dev": true
+    },
+    "node_modules/@apollo/query-graphs/node_modules/uuid": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+      "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+      "dev": true,
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
+    "node_modules/@apollo/query-planner": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-planner/-/query-planner-2.3.1.tgz",
+      "integrity": "sha512-VcW9o1HsTOf2UbKfz+ee1zhTaFvTjenvzgdPSVbv4/EaYF0O1NgVq1UDhOOVcEa5ky7FaLLhRxZI6AImGx5F+A==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-graphs": "2.3.1",
+        "chalk": "^4.1.0",
+        "deep-equal": "^2.0.5",
+        "pretty-format": "^29.0.0"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
     "node_modules/@apollo/server": {
       "resolved": "packages/server",
       "link": true
@@ -200,6 +356,22 @@
       "resolved": "packages/plugin-response-cache",
       "link": true
     },
+    "node_modules/@apollo/subgraph": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/subgraph/-/subgraph-2.3.1.tgz",
+      "integrity": "sha512-xn9SZm1sJNJLfyqtXV8ZxI0tQSsikkjExGCoEfXYqHINDucXRqHtPVlCv5G6k0xhrDQhmmzlvGMzsCuWsUAv4Q==",
+      "dev": true,
+      "dependencies": {
+        "@apollo/cache-control-types": "^1.0.2",
+        "@apollo/federation-internals": "2.3.1"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
     "node_modules/@apollo/usage-reporting-protobuf": {
       "resolved": "packages/usage-reporting-protobuf",
       "link": true
@@ -227,6 +399,12 @@
         "graphql": "14.x || 15.x || 16.x"
       }
     },
+    "node_modules/@apollo/utils.fetcher": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-1.1.1.tgz",
+      "integrity": "sha512-0vXVznO7kw5VWwxyV5wsDvYEwjDpyZ7vYQAXCseLXqBn2eWEIDViM7qRzi/Hnv4zzAQ05phdimSED99K+lg+SQ==",
+      "dev": true
+    },
     "node_modules/@apollo/utils.isnodelike": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.0.tgz",
@@ -4006,6 +4184,27 @@
         "node": ">= 8"
       }
     },
+    "node_modules/@npmcli/fs": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+      "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+      "dev": true,
+      "dependencies": {
+        "semver": "^7.3.5"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/@opentelemetry/api": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.0.tgz",
+      "integrity": "sha512-IgMK9i3sFGNUqPMbjABm0G26g0QCKCUBfglhQ7rQq6WcxbKfEHRcmwsoER4hZcuYqJgkYn2OeuoJIv7Jsftp7g==",
+      "dev": true,
+      "engines": {
+        "node": ">=8.0.0"
+      }
+    },
     "node_modules/@peculiar/asn1-schema": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz",
@@ -4859,6 +5058,29 @@
         "node": ">= 6.0.0"
       }
     },
+    "node_modules/agentkeepalive": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
+      "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
+      "dev": true,
+      "dependencies": {
+        "debug": "^4.1.0",
+        "depd": "^1.1.2",
+        "humanize-ms": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 8.0.0"
+      }
+    },
+    "node_modules/agentkeepalive/node_modules/depd": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+      "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
     "node_modules/aggregate-error": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
@@ -5463,6 +5685,54 @@
         "node": ">= 0.8"
       }
     },
+    "node_modules/cacache": {
+      "version": "17.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz",
+      "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==",
+      "dev": true,
+      "dependencies": {
+        "@npmcli/fs": "^3.1.0",
+        "fs-minipass": "^3.0.0",
+        "glob": "^8.0.1",
+        "lru-cache": "^7.7.1",
+        "minipass": "^4.0.0",
+        "minipass-collect": "^1.0.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.4",
+        "p-map": "^4.0.0",
+        "promise-inflight": "^1.0.1",
+        "ssri": "^10.0.0",
+        "tar": "^6.1.11",
+        "unique-filename": "^3.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/cacache/node_modules/lru-cache": {
+      "version": "7.14.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+      "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/cacache/node_modules/p-map": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+      "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+      "dev": true,
+      "dependencies": {
+        "aggregate-error": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/call-bind": {
       "version": "1.0.2",
       "license": "MIT",
@@ -5631,6 +5901,15 @@
         "fsevents": "~2.3.2"
       }
     },
+    "node_modules/chownr": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "node_modules/ci-info": {
       "version": "3.3.0",
       "license": "MIT"
@@ -6435,6 +6714,34 @@
       "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
       "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
     },
+    "node_modules/deep-equal": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz",
+      "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "es-get-iterator": "^1.1.2",
+        "get-intrinsic": "^1.1.3",
+        "is-arguments": "^1.1.1",
+        "is-array-buffer": "^3.0.1",
+        "is-date-object": "^1.0.5",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.2",
+        "isarray": "^2.0.5",
+        "object-is": "^1.1.5",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.4",
+        "regexp.prototype.flags": "^1.4.3",
+        "side-channel": "^1.0.4",
+        "which-boxed-primitive": "^1.0.2",
+        "which-collection": "^1.0.1",
+        "which-typed-array": "^1.1.9"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/deep-is": {
       "version": "0.1.4",
       "dev": true,
@@ -6715,7 +7022,6 @@
       "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
       "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
       "optional": true,
-      "peer": true,
       "dependencies": {
         "iconv-lite": "^0.6.2"
       }
@@ -6725,7 +7031,6 @@
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
       "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
       "optional": true,
-      "peer": true,
       "dependencies": {
         "safer-buffer": ">= 2.1.2 < 3.0.0"
       },
@@ -6750,6 +7055,12 @@
       "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
       "dev": true
     },
+    "node_modules/err-code": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+      "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+      "dev": true
+    },
     "node_modules/error-ex": {
       "version": "1.3.2",
       "license": "MIT",
@@ -6804,6 +7115,26 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/es-get-iterator": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+      "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.3",
+        "has-symbols": "^1.0.3",
+        "is-arguments": "^1.1.1",
+        "is-map": "^2.0.2",
+        "is-set": "^2.0.2",
+        "is-string": "^1.0.7",
+        "isarray": "^2.0.5",
+        "stop-iteration-iterator": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/es-set-tostringtag": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
@@ -7803,6 +8134,18 @@
         "node": ">=6 <7 || >=8"
       }
     },
+    "node_modules/fs-minipass": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.0.tgz",
+      "integrity": "sha512-EUojgQaSPy6sxcqcZgQv6TVF6jiKvurji3AxhAivs/Ep4O1UpS8TusaxpybfFHZ2skRhLqzk6WR8nqNYIMMDeA==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
     "node_modules/fs.realpath": {
       "version": "1.0.0",
       "license": "ISC"
@@ -8306,6 +8649,12 @@
         "readable-stream": "^3.1.1"
       }
     },
+    "node_modules/http-cache-semantics": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+      "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+      "dev": true
+    },
     "node_modules/http-errors": {
       "version": "2.0.0",
       "license": "MIT",
@@ -8366,6 +8715,15 @@
         "node": ">=10.17.0"
       }
     },
+    "node_modules/humanize-ms": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+      "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+      "dev": true,
+      "dependencies": {
+        "ms": "^2.0.0"
+      }
+    },
     "node_modules/iconv-lite": {
       "version": "0.4.24",
       "license": "MIT",
@@ -8525,8 +8883,9 @@
     },
     "node_modules/ini": {
       "version": "1.3.8",
-      "dev": true,
-      "license": "ISC"
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+      "dev": true
     },
     "node_modules/inquirer": {
       "version": "8.2.2",
@@ -8575,6 +8934,12 @@
         "loose-envify": "^1.0.0"
       }
     },
+    "node_modules/ip": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+      "dev": true
+    },
     "node_modules/ipaddr.js": {
       "version": "1.9.1",
       "license": "MIT",
@@ -8595,6 +8960,22 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-arguments": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-array-buffer": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz",
@@ -8743,6 +9124,12 @@
         "node": ">=8"
       }
     },
+    "node_modules/is-lambda": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+      "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+      "dev": true
+    },
     "node_modules/is-lower-case": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz",
@@ -8752,6 +9139,15 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/is-map": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+      "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-negative-zero": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -8848,6 +9244,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-set": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+      "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-shared-array-buffer": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -8933,8 +9338,9 @@
     },
     "node_modules/is-typedarray": {
       "version": "1.0.0",
-      "dev": true,
-      "license": "MIT"
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+      "dev": true
     },
     "node_modules/is-unc-path": {
       "version": "1.0.0",
@@ -8968,6 +9374,15 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/is-weakmap": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+      "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-weakref": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -8980,6 +9395,19 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-weakset": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+      "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
@@ -8989,6 +9417,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
     "node_modules/isexe": {
       "version": "2.0.0",
       "license": "ISC"
@@ -9698,6 +10132,15 @@
         "url": "https://github.com/chalk/supports-color?sponsor=1"
       }
     },
+    "node_modules/js-levenshtein": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
+      "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/js-sdsl": {
       "version": "4.1.4",
       "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
@@ -10185,6 +10628,42 @@
       "devOptional": true,
       "license": "ISC"
     },
+    "node_modules/make-fetch-happen": {
+      "version": "11.0.2",
+      "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.2.tgz",
+      "integrity": "sha512-5n/Pq41w/uZghpdlXAY5kIM85RgJThtTH/NYBRAZ9VUOBWV90USaQjwGrw76fZP3Lj5hl/VZjpVvOaRBMoL/2w==",
+      "dev": true,
+      "dependencies": {
+        "agentkeepalive": "^4.2.1",
+        "cacache": "^17.0.0",
+        "http-cache-semantics": "^4.1.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.0",
+        "is-lambda": "^1.0.1",
+        "lru-cache": "^7.7.1",
+        "minipass": "^4.0.0",
+        "minipass-collect": "^1.0.2",
+        "minipass-fetch": "^3.0.0",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.4",
+        "negotiator": "^0.6.3",
+        "promise-retry": "^2.0.1",
+        "socks-proxy-agent": "^7.0.0",
+        "ssri": "^10.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/make-fetch-happen/node_modules/lru-cache": {
+      "version": "7.14.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+      "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
     "node_modules/makeerror": {
       "version": "1.0.12",
       "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
@@ -10395,6 +10874,156 @@
         "node": ">= 6"
       }
     },
+    "node_modules/minipass": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz",
+      "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-collect": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+      "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minipass-collect/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-fetch": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz",
+      "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^4.0.0",
+        "minipass-sized": "^1.0.3",
+        "minizlib": "^2.1.2"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      },
+      "optionalDependencies": {
+        "encoding": "^0.1.13"
+      }
+    },
+    "node_modules/minipass-flush": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+      "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minipass-flush/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-pipeline": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+      "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-pipeline/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-sized": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+      "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minipass-sized/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minizlib": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/minizlib/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/mixme": {
       "version": "0.5.4",
       "dev": true,
@@ -10605,6 +11234,22 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/object-is": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+      "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+      "dev": true,
+      "dependencies": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/object-keys": {
       "version": "1.1.1",
       "dev": true,
@@ -11115,6 +11760,34 @@
         "asap": "~2.0.3"
       }
     },
+    "node_modules/promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+      "dev": true
+    },
+    "node_modules/promise-retry": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+      "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+      "dev": true,
+      "dependencies": {
+        "err-code": "^2.0.2",
+        "retry": "^0.12.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/promise-retry/node_modules/retry": {
+      "version": "0.12.0",
+      "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+      "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
     "node_modules/prompts": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -11916,6 +12589,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/smart-buffer": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 6.0.0",
+        "npm": ">= 3.0.0"
+      }
+    },
     "node_modules/smartwrap": {
       "version": "2.0.2",
       "dev": true,
@@ -12006,6 +12689,34 @@
         "tslib": "^2.0.3"
       }
     },
+    "node_modules/socks": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
+      "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
+      "dev": true,
+      "dependencies": {
+        "ip": "^2.0.0",
+        "smart-buffer": "^4.2.0"
+      },
+      "engines": {
+        "node": ">= 10.13.0",
+        "npm": ">= 3.0.0"
+      }
+    },
+    "node_modules/socks-proxy-agent": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+      "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+      "dev": true,
+      "dependencies": {
+        "agent-base": "^6.0.2",
+        "debug": "^4.3.3",
+        "socks": "^2.6.2"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
     "node_modules/source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -12134,6 +12845,18 @@
       "version": "1.0.3",
       "license": "BSD-3-Clause"
     },
+    "node_modules/ssri": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.1.tgz",
+      "integrity": "sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
     "node_modules/stack-utils": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
@@ -12161,6 +12884,18 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/stop-iteration-iterator": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+      "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+      "dev": true,
+      "dependencies": {
+        "internal-slot": "^1.0.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
     "node_modules/stream-events": {
       "version": "1.0.5",
       "dev": true,
@@ -12403,6 +13138,47 @@
         "node": ">=0.10"
       }
     },
+    "node_modules/tar": {
+      "version": "6.1.13",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz",
+      "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==",
+      "dev": true,
+      "dependencies": {
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "minipass": "^4.0.0",
+        "minizlib": "^2.1.1",
+        "mkdirp": "^1.0.3",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tar/node_modules/fs-minipass": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+      "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+      "dev": true,
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": {
+      "version": "3.3.6",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+      "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/teeny-request": {
       "version": "7.1.1",
       "dev": true,
@@ -12592,6 +13368,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/ts-graphviz": {
+      "version": "0.16.0",
+      "resolved": "https://registry.npmjs.org/ts-graphviz/-/ts-graphviz-0.16.0.tgz",
+      "integrity": "sha512-3fTPO+G6bSQNvMh/XQQzyiahVLMMj9kqYO99ivUraNJ3Wp05HZOOVtRhi6w9hq7+laP1MKHjLBtGWqTeb1fcpg==",
+      "dev": true,
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/kamiazya"
+      }
+    },
     "node_modules/ts-invariant": {
       "version": "0.10.3",
       "license": "MIT",
@@ -12906,6 +13692,30 @@
         "node": ">=12.18"
       }
     },
+    "node_modules/unique-filename": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+      "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+      "dev": true,
+      "dependencies": {
+        "unique-slug": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
+    "node_modules/unique-slug": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+      "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+      "dev": true,
+      "dependencies": {
+        "imurmurhash": "^0.1.4"
+      },
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
     "node_modules/unique-string": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
@@ -13193,6 +14003,21 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/which-collection": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+      "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+      "dev": true,
+      "dependencies": {
+        "is-map": "^2.0.1",
+        "is-set": "^2.0.1",
+        "is-weakmap": "^2.0.1",
+        "is-weakset": "^2.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/which-module": {
       "version": "2.0.0",
       "dev": true,
@@ -13686,6 +14511,82 @@
         }
       }
     },
+    "@apollo/composition": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/composition/-/composition-2.3.1.tgz",
+      "integrity": "sha512-lNPBGkNTcWhEHFLjlWAr/ViqpMNOj+BxDPSktqp/Pd1dxWOzUuDLHSGjJY4ESKrBE2RhQ9Nb3jIKbsLmjF6jNg==",
+      "dev": true,
+      "requires": {
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-graphs": "2.3.1"
+      }
+    },
+    "@apollo/federation-internals": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/federation-internals/-/federation-internals-2.3.1.tgz",
+      "integrity": "sha512-XLsXLeEFBGZ5lhj4huEJTP5TAq3+t+EXqoFAEFX8hSQMAJ+lW+w51YZMbB4R7naojFf1ehlHSAit523GTE9aMA==",
+      "dev": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "js-levenshtein": "^1.1.6"
+      }
+    },
+    "@apollo/gateway": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/gateway/-/gateway-2.3.1.tgz",
+      "integrity": "sha512-kkZP591To697XL8rH6JOvStOU7URcHInKWEU2q3Llimwt4Gm1mlshlNNnlRiHy2ri6tim0/wL1qLBtFG2LUfDQ==",
+      "dev": true,
+      "requires": {
+        "@apollo/composition": "2.3.1",
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-planner": "2.3.1",
+        "@apollo/server-gateway-interface": "^1.1.0",
+        "@apollo/usage-reporting-protobuf": "^4.0.0",
+        "@apollo/utils.createhash": "^1.1.0",
+        "@apollo/utils.fetcher": "^1.1.0",
+        "@apollo/utils.isnodelike": "^1.1.0",
+        "@apollo/utils.logger": "^1.0.0",
+        "@josephg/resolvable": "^1.0.1",
+        "@opentelemetry/api": "^1.0.1",
+        "@types/node-fetch": "^2.6.2",
+        "async-retry": "^1.3.3",
+        "loglevel": "^1.6.1",
+        "lru-cache": "^7.13.1",
+        "make-fetch-happen": "^11.0.0",
+        "node-abort-controller": "^3.0.1",
+        "node-fetch": "^2.6.7"
+      },
+      "dependencies": {
+        "@apollo/utils.createhash": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-1.1.0.tgz",
+          "integrity": "sha512-5fT4ZiW75515OlikWpIQzaVDws1yy9VgYSoHoJCrvI2UH6/7YNKXQjbjT5qVYu6ytch2wBxFMfFfYWMn/2bSCQ==",
+          "dev": true,
+          "requires": {
+            "@apollo/utils.isnodelike": "^1.1.0",
+            "sha.js": "^2.4.11"
+          }
+        },
+        "@apollo/utils.isnodelike": {
+          "version": "1.1.0",
+          "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-1.1.0.tgz",
+          "integrity": "sha512-q/Q82kBUSEcx1ED11JO1TYBY781mWluUnBD8NvhjHVsu1K1C5R9BZVUxShyK/V8XcePcRUB5fdWOcBMGwS0KOA==",
+          "dev": true
+        },
+        "@apollo/utils.logger": {
+          "version": "1.0.1",
+          "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-1.0.1.tgz",
+          "integrity": "sha512-XdlzoY7fYNK4OIcvMD2G94RoFZbzTQaNP0jozmqqMudmaGo2I/2Jx71xlDJ801mWA/mbYRihyaw6KJii7k5RVA==",
+          "dev": true
+        },
+        "lru-cache": {
+          "version": "7.14.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+          "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+          "dev": true
+        }
+      }
+    },
     "@apollo/protobufjs": {
       "version": "1.2.7",
       "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.7.tgz",
@@ -13705,6 +14606,46 @@
         "long": "^4.0.0"
       }
     },
+    "@apollo/query-graphs": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-graphs/-/query-graphs-2.3.1.tgz",
+      "integrity": "sha512-mvEBk3KTrKr5Av3KlwPG+1Ve8vPngNxLb0NSc49FHGEticpd/p8ZV6hD2Jh8LNLdhEu5g0POr78b+mtJccqo4g==",
+      "dev": true,
+      "requires": {
+        "@apollo/federation-internals": "2.3.1",
+        "@types/uuid": "^8.3.4",
+        "deep-equal": "^2.0.5",
+        "ts-graphviz": "^0.16.0",
+        "uuid": "^9.0.0"
+      },
+      "dependencies": {
+        "@types/uuid": {
+          "version": "8.3.4",
+          "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+          "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
+          "dev": true
+        },
+        "uuid": {
+          "version": "9.0.0",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz",
+          "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==",
+          "dev": true
+        }
+      }
+    },
+    "@apollo/query-planner": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-planner/-/query-planner-2.3.1.tgz",
+      "integrity": "sha512-VcW9o1HsTOf2UbKfz+ee1zhTaFvTjenvzgdPSVbv4/EaYF0O1NgVq1UDhOOVcEa5ky7FaLLhRxZI6AImGx5F+A==",
+      "dev": true,
+      "requires": {
+        "@apollo/federation-internals": "2.3.1",
+        "@apollo/query-graphs": "2.3.1",
+        "chalk": "^4.1.0",
+        "deep-equal": "^2.0.5",
+        "pretty-format": "^29.0.0"
+      }
+    },
     "@apollo/server": {
       "version": "file:packages/server",
       "requires": {
@@ -13859,6 +14800,16 @@
         }
       }
     },
+    "@apollo/subgraph": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/@apollo/subgraph/-/subgraph-2.3.1.tgz",
+      "integrity": "sha512-xn9SZm1sJNJLfyqtXV8ZxI0tQSsikkjExGCoEfXYqHINDucXRqHtPVlCv5G6k0xhrDQhmmzlvGMzsCuWsUAv4Q==",
+      "dev": true,
+      "requires": {
+        "@apollo/cache-control-types": "^1.0.2",
+        "@apollo/federation-internals": "2.3.1"
+      }
+    },
     "@apollo/usage-reporting-protobuf": {
       "version": "file:packages/usage-reporting-protobuf",
       "requires": {
@@ -13880,6 +14831,12 @@
       "integrity": "sha512-BoPW+Z3kA8kLh0FCWyzOt+R77W5mVZWer5s6UyvVwZ/qROGiEgcHXFcI5TMMndpXoDo0xBSvQV0lIKYHbJQ7+g==",
       "requires": {}
     },
+    "@apollo/utils.fetcher": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-1.1.1.tgz",
+      "integrity": "sha512-0vXVznO7kw5VWwxyV5wsDvYEwjDpyZ7vYQAXCseLXqBn2eWEIDViM7qRzi/Hnv4zzAQ05phdimSED99K+lg+SQ==",
+      "dev": true
+    },
     "@apollo/utils.isnodelike": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.0.tgz",
@@ -16919,6 +17876,21 @@
         "fastq": "^1.6.0"
       }
     },
+    "@npmcli/fs": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz",
+      "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==",
+      "dev": true,
+      "requires": {
+        "semver": "^7.3.5"
+      }
+    },
+    "@opentelemetry/api": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.4.0.tgz",
+      "integrity": "sha512-IgMK9i3sFGNUqPMbjABm0G26g0QCKCUBfglhQ7rQq6WcxbKfEHRcmwsoER4hZcuYqJgkYn2OeuoJIv7Jsftp7g==",
+      "dev": true
+    },
     "@peculiar/asn1-schema": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.2.0.tgz",
@@ -17577,6 +18549,25 @@
         "debug": "4"
       }
     },
+    "agentkeepalive": {
+      "version": "4.2.1",
+      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.1.tgz",
+      "integrity": "sha512-Zn4cw2NEqd+9fiSVWMscnjyQ1a8Yfoc5oBajLeo5w+YBHgDUcEBY2hS4YpTz6iN5f/2zQiktcuM6tS8x1p9dpA==",
+      "dev": true,
+      "requires": {
+        "debug": "^4.1.0",
+        "depd": "^1.1.2",
+        "humanize-ms": "^1.2.1"
+      },
+      "dependencies": {
+        "depd": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+          "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+          "dev": true
+        }
+      }
+    },
     "aggregate-error": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
@@ -17988,6 +18979,44 @@
     "bytes": {
       "version": "3.1.2"
     },
+    "cacache": {
+      "version": "17.0.4",
+      "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.0.4.tgz",
+      "integrity": "sha512-Z/nL3gU+zTUjz5pCA5vVjYM8pmaw2kxM7JEiE0fv3w77Wj+sFbi70CrBruUWH0uNcEdvLDixFpgA2JM4F4DBjA==",
+      "dev": true,
+      "requires": {
+        "@npmcli/fs": "^3.1.0",
+        "fs-minipass": "^3.0.0",
+        "glob": "^8.0.1",
+        "lru-cache": "^7.7.1",
+        "minipass": "^4.0.0",
+        "minipass-collect": "^1.0.2",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.4",
+        "p-map": "^4.0.0",
+        "promise-inflight": "^1.0.1",
+        "ssri": "^10.0.0",
+        "tar": "^6.1.11",
+        "unique-filename": "^3.0.0"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "7.14.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+          "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+          "dev": true
+        },
+        "p-map": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+          "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+          "dev": true,
+          "requires": {
+            "aggregate-error": "^3.0.0"
+          }
+        }
+      }
+    },
     "call-bind": {
       "version": "1.0.2",
       "requires": {
@@ -18104,6 +19133,12 @@
         "readdirp": "~3.6.0"
       }
     },
+    "chownr": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+      "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+      "dev": true
+    },
     "ci-info": {
       "version": "3.3.0"
     },
@@ -18686,6 +19721,31 @@
       "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz",
       "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA=="
     },
+    "deep-equal": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz",
+      "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "es-get-iterator": "^1.1.2",
+        "get-intrinsic": "^1.1.3",
+        "is-arguments": "^1.1.1",
+        "is-array-buffer": "^3.0.1",
+        "is-date-object": "^1.0.5",
+        "is-regex": "^1.1.4",
+        "is-shared-array-buffer": "^1.0.2",
+        "isarray": "^2.0.5",
+        "object-is": "^1.1.5",
+        "object-keys": "^1.1.1",
+        "object.assign": "^4.1.4",
+        "regexp.prototype.flags": "^1.4.3",
+        "side-channel": "^1.0.4",
+        "which-boxed-primitive": "^1.0.2",
+        "which-collection": "^1.0.1",
+        "which-typed-array": "^1.1.9"
+      }
+    },
     "deep-is": {
       "version": "0.1.4",
       "dev": true
@@ -18888,7 +19948,6 @@
       "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
       "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
       "optional": true,
-      "peer": true,
       "requires": {
         "iconv-lite": "^0.6.2"
       },
@@ -18898,7 +19957,6 @@
           "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
           "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
           "optional": true,
-          "peer": true,
           "requires": {
             "safer-buffer": ">= 2.1.2 < 3.0.0"
           }
@@ -18918,6 +19976,12 @@
       "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
       "dev": true
     },
+    "err-code": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+      "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+      "dev": true
+    },
     "error-ex": {
       "version": "1.3.2",
       "requires": {
@@ -18965,6 +20029,23 @@
         "which-typed-array": "^1.1.9"
       }
     },
+    "es-get-iterator": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
+      "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.3",
+        "has-symbols": "^1.0.3",
+        "is-arguments": "^1.1.1",
+        "is-map": "^2.0.2",
+        "is-set": "^2.0.2",
+        "is-string": "^1.0.7",
+        "isarray": "^2.0.5",
+        "stop-iteration-iterator": "^1.0.0"
+      }
+    },
     "es-set-tostringtag": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
@@ -19709,6 +20790,15 @@
         "universalify": "^0.1.0"
       }
     },
+    "fs-minipass": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.0.tgz",
+      "integrity": "sha512-EUojgQaSPy6sxcqcZgQv6TVF6jiKvurji3AxhAivs/Ep4O1UpS8TusaxpybfFHZ2skRhLqzk6WR8nqNYIMMDeA==",
+      "dev": true,
+      "requires": {
+        "minipass": "^4.0.0"
+      }
+    },
     "fs.realpath": {
       "version": "1.0.0"
     },
@@ -20038,6 +21128,12 @@
         "readable-stream": "^3.1.1"
       }
     },
+    "http-cache-semantics": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
+      "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==",
+      "dev": true
+    },
     "http-errors": {
       "version": "2.0.0",
       "requires": {
@@ -20081,6 +21177,15 @@
       "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
       "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="
     },
+    "humanize-ms": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+      "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+      "dev": true,
+      "requires": {
+        "ms": "^2.0.0"
+      }
+    },
     "iconv-lite": {
       "version": "0.4.24",
       "requires": {
@@ -20172,6 +21277,8 @@
     },
     "ini": {
       "version": "1.3.8",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
       "dev": true
     },
     "inquirer": {
@@ -20214,6 +21321,12 @@
         "loose-envify": "^1.0.0"
       }
     },
+    "ip": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
+      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
+      "dev": true
+    },
     "ipaddr.js": {
       "version": "1.9.1"
     },
@@ -20227,6 +21340,16 @@
         "is-windows": "^1.0.1"
       }
     },
+    "is-arguments": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+      "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "has-tostringtag": "^1.0.0"
+      }
+    },
     "is-array-buffer": {
       "version": "3.0.1",
       "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz",
@@ -20320,6 +21443,12 @@
       "version": "1.0.0",
       "dev": true
     },
+    "is-lambda": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+      "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+      "dev": true
+    },
     "is-lower-case": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz",
@@ -20329,6 +21458,12 @@
         "tslib": "^2.0.3"
       }
     },
+    "is-map": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
+      "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
+      "dev": true
+    },
     "is-negative-zero": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -20389,6 +21524,12 @@
         "is-unc-path": "^1.0.0"
       }
     },
+    "is-set": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
+      "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+      "dev": true
+    },
     "is-shared-array-buffer": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -20443,6 +21584,8 @@
     },
     "is-typedarray": {
       "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+      "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
       "dev": true
     },
     "is-unc-path": {
@@ -20467,6 +21610,12 @@
         "tslib": "^2.0.3"
       }
     },
+    "is-weakmap": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
+      "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+      "dev": true
+    },
     "is-weakref": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -20476,12 +21625,28 @@
         "call-bind": "^1.0.2"
       }
     },
+    "is-weakset": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+      "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "get-intrinsic": "^1.1.1"
+      }
+    },
     "is-windows": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
       "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
       "dev": true
     },
+    "isarray": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "dev": true
+    },
     "isexe": {
       "version": "2.0.0"
     },
@@ -21022,6 +22187,12 @@
         }
       }
     },
+    "js-levenshtein": {
+      "version": "1.1.6",
+      "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
+      "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
+      "dev": true
+    },
     "js-sdsl": {
       "version": "4.1.4",
       "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz",
@@ -21369,6 +22540,38 @@
       "version": "1.3.6",
       "devOptional": true
     },
+    "make-fetch-happen": {
+      "version": "11.0.2",
+      "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.0.2.tgz",
+      "integrity": "sha512-5n/Pq41w/uZghpdlXAY5kIM85RgJThtTH/NYBRAZ9VUOBWV90USaQjwGrw76fZP3Lj5hl/VZjpVvOaRBMoL/2w==",
+      "dev": true,
+      "requires": {
+        "agentkeepalive": "^4.2.1",
+        "cacache": "^17.0.0",
+        "http-cache-semantics": "^4.1.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.0",
+        "is-lambda": "^1.0.1",
+        "lru-cache": "^7.7.1",
+        "minipass": "^4.0.0",
+        "minipass-collect": "^1.0.2",
+        "minipass-fetch": "^3.0.0",
+        "minipass-flush": "^1.0.5",
+        "minipass-pipeline": "^1.2.4",
+        "negotiator": "^0.6.3",
+        "promise-retry": "^2.0.1",
+        "socks-proxy-agent": "^7.0.0",
+        "ssri": "^10.0.0"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "7.14.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+          "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
+          "dev": true
+        }
+      }
+    },
     "makeerror": {
       "version": "1.0.12",
       "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
@@ -21493,6 +22696,128 @@
         "kind-of": "^6.0.3"
       }
     },
+    "minipass": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz",
+      "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==",
+      "dev": true,
+      "requires": {
+        "yallist": "^4.0.0"
+      }
+    },
+    "minipass-collect": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+      "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+      "dev": true,
+      "requires": {
+        "minipass": "^3.0.0"
+      },
+      "dependencies": {
+        "minipass": {
+          "version": "3.3.6",
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+          "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        }
+      }
+    },
+    "minipass-fetch": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.1.tgz",
+      "integrity": "sha512-t9/wowtf7DYkwz8cfMSt0rMwiyNIBXf5CKZ3S5ZMqRqMYT0oLTp0x1WorMI9WTwvaPg21r1JbFxJMum8JrLGfw==",
+      "dev": true,
+      "requires": {
+        "encoding": "^0.1.13",
+        "minipass": "^4.0.0",
+        "minipass-sized": "^1.0.3",
+        "minizlib": "^2.1.2"
+      }
+    },
+    "minipass-flush": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+      "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+      "dev": true,
+      "requires": {
+        "minipass": "^3.0.0"
+      },
+      "dependencies": {
+        "minipass": {
+          "version": "3.3.6",
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+          "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        }
+      }
+    },
+    "minipass-pipeline": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+      "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+      "dev": true,
+      "requires": {
+        "minipass": "^3.0.0"
+      },
+      "dependencies": {
+        "minipass": {
+          "version": "3.3.6",
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+          "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        }
+      }
+    },
+    "minipass-sized": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+      "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+      "dev": true,
+      "requires": {
+        "minipass": "^3.0.0"
+      },
+      "dependencies": {
+        "minipass": {
+          "version": "3.3.6",
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+          "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        }
+      }
+    },
+    "minizlib": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+      "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+      "dev": true,
+      "requires": {
+        "minipass": "^3.0.0",
+        "yallist": "^4.0.0"
+      },
+      "dependencies": {
+        "minipass": {
+          "version": "3.3.6",
+          "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+          "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+          "dev": true,
+          "requires": {
+            "yallist": "^4.0.0"
+          }
+        }
+      }
+    },
     "mixme": {
       "version": "0.5.4",
       "dev": true
@@ -21636,6 +22961,16 @@
       "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz",
       "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g=="
     },
+    "object-is": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
+      "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+      "dev": true,
+      "requires": {
+        "call-bind": "^1.0.2",
+        "define-properties": "^1.1.3"
+      }
+    },
     "object-keys": {
       "version": "1.1.1",
       "dev": true
@@ -21970,6 +23305,30 @@
         "asap": "~2.0.3"
       }
     },
+    "promise-inflight": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+      "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+      "dev": true
+    },
+    "promise-retry": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+      "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+      "dev": true,
+      "requires": {
+        "err-code": "^2.0.2",
+        "retry": "^0.12.0"
+      },
+      "dependencies": {
+        "retry": {
+          "version": "0.12.0",
+          "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+          "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+          "dev": true
+        }
+      }
+    },
     "prompts": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -22508,6 +23867,12 @@
     "slash": {
       "version": "3.0.0"
     },
+    "smart-buffer": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+      "dev": true
+    },
     "smartwrap": {
       "version": "2.0.2",
       "dev": true,
@@ -22579,6 +23944,27 @@
         "tslib": "^2.0.3"
       }
     },
+    "socks": {
+      "version": "2.7.1",
+      "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
+      "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
+      "dev": true,
+      "requires": {
+        "ip": "^2.0.0",
+        "smart-buffer": "^4.2.0"
+      }
+    },
+    "socks-proxy-agent": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz",
+      "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^6.0.2",
+        "debug": "^4.3.3",
+        "socks": "^2.6.2"
+      }
+    },
     "source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -22692,6 +24078,15 @@
     "sprintf-js": {
       "version": "1.0.3"
     },
+    "ssri": {
+      "version": "10.0.1",
+      "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.1.tgz",
+      "integrity": "sha512-WVy6di9DlPOeBWEjMScpNipeSX2jIZBGEn5Uuo8Q7aIuFEuDX0pw8RxcOjlD1TWP4obi24ki7m/13+nFpcbXrw==",
+      "dev": true,
+      "requires": {
+        "minipass": "^4.0.0"
+      }
+    },
     "stack-utils": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz",
@@ -22711,6 +24106,15 @@
       "version": "1.5.0",
       "dev": true
     },
+    "stop-iteration-iterator": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz",
+      "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==",
+      "dev": true,
+      "requires": {
+        "internal-slot": "^1.0.4"
+      }
+    },
     "stream-events": {
       "version": "1.0.5",
       "dev": true,
@@ -22882,6 +24286,42 @@
     "symbol-observable": {
       "version": "4.0.0"
     },
+    "tar": {
+      "version": "6.1.13",
+      "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz",
+      "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==",
+      "dev": true,
+      "requires": {
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "minipass": "^4.0.0",
+        "minizlib": "^2.1.1",
+        "mkdirp": "^1.0.3",
+        "yallist": "^4.0.0"
+      },
+      "dependencies": {
+        "fs-minipass": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+          "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+          "dev": true,
+          "requires": {
+            "minipass": "^3.0.0"
+          },
+          "dependencies": {
+            "minipass": {
+              "version": "3.3.6",
+              "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+              "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+              "dev": true,
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            }
+          }
+        }
+      }
+    },
     "teeny-request": {
       "version": "7.1.1",
       "dev": true,
@@ -23013,6 +24453,12 @@
       "version": "3.0.1",
       "dev": true
     },
+    "ts-graphviz": {
+      "version": "0.16.0",
+      "resolved": "https://registry.npmjs.org/ts-graphviz/-/ts-graphviz-0.16.0.tgz",
+      "integrity": "sha512-3fTPO+G6bSQNvMh/XQQzyiahVLMMj9kqYO99ivUraNJ3Wp05HZOOVtRhi6w9hq7+laP1MKHjLBtGWqTeb1fcpg==",
+      "dev": true
+    },
     "ts-invariant": {
       "version": "0.10.3",
       "requires": {
@@ -23201,6 +24647,24 @@
         "busboy": "^1.6.0"
       }
     },
+    "unique-filename": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz",
+      "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==",
+      "dev": true,
+      "requires": {
+        "unique-slug": "^4.0.0"
+      }
+    },
+    "unique-slug": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz",
+      "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==",
+      "dev": true,
+      "requires": {
+        "imurmurhash": "^0.1.4"
+      }
+    },
     "unique-string": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
@@ -23415,6 +24879,18 @@
         "is-symbol": "^1.0.3"
       }
     },
+    "which-collection": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
+      "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+      "dev": true,
+      "requires": {
+        "is-map": "^2.0.1",
+        "is-set": "^2.0.1",
+        "is-weakmap": "^2.0.1",
+        "is-weakset": "^2.0.1"
+      }
+    },
     "which-module": {
       "version": "2.0.0",
       "dev": true
diff --git a/package.json b/package.json
index 3f32fab5f..3859938d8 100644
--- a/package.json
+++ b/package.json
@@ -38,7 +38,9 @@
   },
   "devDependencies": {
     "@apollo/client": "3.7.7",
+    "@apollo/gateway": "2.3.1",
     "@apollo/server-plugin-landing-page-graphql-playground": "4.0.0",
+    "@apollo/subgraph": "2.3.1",
     "@apollo/utils.createhash": "2.0.0",
     "@changesets/changelog-github": "0.4.8",
     "@changesets/cli": "2.26.0",
diff --git a/packages/server/src/externalTypes/requestPipeline.ts b/packages/server/src/externalTypes/requestPipeline.ts
index da84237cb..75445cc7d 100644
--- a/packages/server/src/externalTypes/requestPipeline.ts
+++ b/packages/server/src/externalTypes/requestPipeline.ts
@@ -19,6 +19,7 @@ import type {
   OperationDefinitionNode,
 } from 'graphql';
 import type { CachePolicy } from '@apollo/cache-control-types';
+import type { NonFtv1ErrorPath } from '@apollo/server-gateway-interface';
 
 export interface GraphQLRequestMetrics {
   // It would be more accurate to call this fieldLevelInstrumentation (it is
@@ -33,6 +34,7 @@ export interface GraphQLRequestMetrics {
   registeredOperation?: boolean;
   startHrTime?: [number, number];
   queryPlanTrace?: Trace.QueryPlanNode;
+  nonFtv1ErrorPaths?: NonFtv1ErrorPath[];
 }
 
 export interface GraphQLRequestContext<TContext extends BaseContext> {
diff --git a/packages/server/src/plugin/usageReporting/plugin.ts b/packages/server/src/plugin/usageReporting/plugin.ts
index 9b7824e0d..ae877d607 100644
--- a/packages/server/src/plugin/usageReporting/plugin.ts
+++ b/packages/server/src/plugin/usageReporting/plugin.ts
@@ -722,11 +722,12 @@ export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
             getReportWhichMustBeUsedImmediately(executableSchemaId).addTrace({
               statsReportKey,
               trace,
-              // We include the operation as a trace (rather than aggregated
-              // into stats) only if the user didn't set `sendTraces: false`
-              // *and* we believe it's possible that our organization's plan
-              // allows for viewing traces *and* we actually captured this as
-              // a full trace *and* sendOperationAsTrace says so.
+              // We include the operation as a trace (rather than aggregated into stats) only if:
+              // * the user didn't set `sendTraces: false` AND
+              // * it's possible that the organization's plan allows for viewing traces AND
+              // * we captured this as a full trace AND
+              // * gateway reported no errors missing ftv1 data AND
+              // * sendOperationAsTrace says so
               //
               // (As an edge case, if the reason metrics.captureTraces is
               // falsey is that this is an unexecutable operation and thus we
@@ -737,8 +738,10 @@ export function ApolloServerPluginUsageReporting<TContext extends BaseContext>(
               asTrace:
                 sendTraces &&
                 (!isExecutable || !!metrics.captureTraces) &&
+                !metrics.nonFtv1ErrorPaths?.length &&
                 sendOperationAsTrace(trace, statsReportKey),
               referencedFieldsByType,
+              nonFtv1ErrorPaths: metrics.nonFtv1ErrorPaths ?? [],
             });
 
             // If the buffer gets big (according to our estimate), send.
diff --git a/packages/server/src/plugin/usageReporting/stats.ts b/packages/server/src/plugin/usageReporting/stats.ts
index 302e67eb5..29547f527 100644
--- a/packages/server/src/plugin/usageReporting/stats.ts
+++ b/packages/server/src/plugin/usageReporting/stats.ts
@@ -1,3 +1,4 @@
+import type { NonFtv1ErrorPath } from '@apollo/server-gateway-interface';
 import {
   type google,
   type IContextualizedStats,
@@ -65,12 +66,14 @@ export class OurReport implements Required<IReport> {
     // Apollo reporting ingress server will never store any traces over 10mb
     // anyway. They will still be converted to stats as we would do here.
     maxTraceBytes = 10 * 1024 * 1024,
+    nonFtv1ErrorPaths,
   }: {
     statsReportKey: string;
     trace: Trace;
     asTrace: boolean;
     referencedFieldsByType: ReferencedFieldsByType;
     maxTraceBytes?: number;
+    nonFtv1ErrorPaths: NonFtv1ErrorPath[];
   }) {
     const tracesAndStats = this.getTracesAndStats({
       statsReportKey,
@@ -80,13 +83,21 @@ export class OurReport implements Required<IReport> {
       const encodedTrace = Trace.encode(trace).finish();
 
       if (!isNaN(maxTraceBytes) && encodedTrace.length > maxTraceBytes) {
-        tracesAndStats.statsWithContext.addTrace(trace, this.sizeEstimator);
+        tracesAndStats.statsWithContext.addTrace(
+          trace,
+          this.sizeEstimator,
+          nonFtv1ErrorPaths,
+        );
       } else {
         tracesAndStats.trace.push(encodedTrace);
         this.sizeEstimator.bytes += 2 + encodedTrace.length;
       }
     } else {
-      tracesAndStats.statsWithContext.addTrace(trace, this.sizeEstimator);
+      tracesAndStats.statsWithContext.addTrace(
+        trace,
+        this.sizeEstimator,
+        nonFtv1ErrorPaths,
+      );
     }
   }
 
@@ -157,10 +168,15 @@ class StatsByContext {
     }
   }
 
-  addTrace(trace: Trace, sizeEstimator: SizeEstimator) {
+  addTrace(
+    trace: Trace,
+    sizeEstimator: SizeEstimator,
+    nonFtv1ErrorPaths: NonFtv1ErrorPath[],
+  ) {
     this.getContextualizedStats(trace, sizeEstimator).addTrace(
       trace,
       sizeEstimator,
+      nonFtv1ErrorPaths,
     );
   }
 
@@ -207,7 +223,11 @@ export class OurContextualizedStats implements Required<IContextualizedStats> {
   // We only add to the estimate when adding whole sub-messages. If it really
   // mattered, we could do a lot more careful things like incrementing it
   // whenever a numeric field on queryLatencyStats gets incremented over 0.
-  addTrace(trace: Trace, sizeEstimator: SizeEstimator) {
+  addTrace(
+    trace: Trace,
+    sizeEstimator: SizeEstimator,
+    nonFtv1ErrorPaths: NonFtv1ErrorPath[] = [],
+  ) {
     const { fieldExecutionWeight } = trace;
     if (!fieldExecutionWeight) {
       this.queryLatencyStats.requestsWithoutFieldInstrumentation++;
@@ -258,6 +278,8 @@ export class OurContextualizedStats implements Required<IContextualizedStats> {
 
     let hasError = false;
 
+    const errorPathStats = new Set<OurPathErrorStats>();
+
     const traceNodeStats = (node: Trace.INode, path: ResponseNamePath) => {
       // Generate error stats and error path information
       if (node.error?.length) {
@@ -271,7 +293,7 @@ export class OurContextualizedStats implements Required<IContextualizedStats> {
           );
         });
 
-        currPathErrorStats.requestsWithErrorsCount += 1;
+        errorPathStats.add(currPathErrorStats);
         currPathErrorStats.errorsCount += node.error.length;
       }
 
@@ -331,6 +353,33 @@ export class OurContextualizedStats implements Required<IContextualizedStats> {
     };
 
     iterateOverTrace(trace, traceNodeStats, true);
+
+    // iterate over nonFtv1ErrorPaths, using some bits from traceNodeStats function
+    for (const { subgraph, path } of nonFtv1ErrorPaths) {
+      hasError = true;
+      if (path) {
+        let currPathErrorStats = this.queryLatencyStats.rootErrorStats.getChild(
+          `service:${subgraph}`,
+          sizeEstimator,
+        );
+        path.forEach((subPath) => {
+          if (typeof subPath === 'string') {
+            currPathErrorStats = currPathErrorStats.getChild(
+              subPath,
+              sizeEstimator,
+            );
+          }
+        });
+
+        errorPathStats.add(currPathErrorStats);
+        currPathErrorStats.errorsCount += 1;
+      }
+    }
+
+    for (const errorPath of errorPathStats) {
+      errorPath.requestsWithErrorsCount += 1;
+    }
+
     if (hasError) {
       this.queryLatencyStats.requestsWithErrorsCount++;
     }


Test patch:
diff --git a/packages/server/src/__tests__/nockAssertions.ts b/packages/server/src/__tests__/nockAssertions.ts
new file mode 100644
index 000000000..d939a01df
--- /dev/null
+++ b/packages/server/src/__tests__/nockAssertions.ts
@@ -0,0 +1,21 @@
+import { expect } from '@jest/globals';
+import nock from 'nock';
+
+// Ensures an active and clean nock before every test
+export function nockBeforeEach() {
+  if (!nock.isActive()) {
+    nock.activate();
+  }
+  // Cleaning _before_ each test ensures that any mocks from a previous test
+  // which failed don't affect the current test.
+  nock.cleanAll();
+}
+
+// Ensures a test is complete (all expected requests were run) and a clean
+// global state after each test.
+export function nockAfterEach() {
+  // un-mock HTTP interceptor
+  nock.restore();
+  // effectively nock.isDone() but with more helpful messages in test failures
+  expect(nock.activeMocks()).toEqual([]);
+}
diff --git a/packages/server/src/__tests__/plugin/usageReporting/stats.test.ts b/packages/server/src/__tests__/plugin/usageReporting/stats.test.ts
index 2e0824b1a..9edee65a6 100644
--- a/packages/server/src/__tests__/plugin/usageReporting/stats.test.ts
+++ b/packages/server/src/__tests__/plugin/usageReporting/stats.test.ts
@@ -501,6 +501,7 @@ describe('Add trace to report', () => {
       trace: baseTrace,
       asTrace: false,
       referencedFieldsByType,
+      nonFtv1ErrorPaths: [],
     });
 
     expect(report.tracesPerQuery['key']?.trace?.length).toBe(0);
@@ -517,6 +518,7 @@ describe('Add trace to report', () => {
       asTrace: true,
       referencedFieldsByType,
       maxTraceBytes: 10,
+      nonFtv1ErrorPaths: [],
     });
 
     expect(report.tracesPerQuery['key']?.trace?.length).toBe(0);
@@ -533,6 +535,7 @@ describe('Add trace to report', () => {
       asTrace: true,
       referencedFieldsByType,
       maxTraceBytes: 500 * 1024,
+      nonFtv1ErrorPaths: [],
     });
 
     expect(report.tracesPerQuery['key']?.trace?.length).toBe(1);
@@ -548,6 +551,7 @@ describe('Add trace to report', () => {
       trace: baseTrace,
       asTrace: true,
       referencedFieldsByType,
+      nonFtv1ErrorPaths: [],
     });
 
     expect(report.tracesPerQuery['key']?.trace?.length).toBe(1);
diff --git a/packages/server/src/__tests__/plugin/usageReporting/statsErrors.test.ts b/packages/server/src/__tests__/plugin/usageReporting/statsErrors.test.ts
new file mode 100644
index 000000000..a4fc53b84
--- /dev/null
+++ b/packages/server/src/__tests__/plugin/usageReporting/statsErrors.test.ts
@@ -0,0 +1,598 @@
+import {
+  ApolloGateway,
+  IntrospectAndCompose,
+  ServiceEndpointDefinition,
+} from '@apollo/gateway';
+import { buildSubgraphSchema } from '@apollo/subgraph';
+import { IContextualizedStats, Report } from '@apollo/usage-reporting-protobuf';
+import type { Logger } from '@apollo/utils.logger';
+import { afterEach, beforeEach, describe, expect, it } from '@jest/globals';
+import gql from 'graphql-tag';
+import nock from 'nock';
+import { gunzipSync } from 'zlib';
+import { ApolloServer } from '../../../ApolloServer';
+import type { BaseContext } from '../../../externalTypes';
+import { ApolloServerPluginUsageReportingDisabled } from '../../../plugin/disabled';
+import {
+  ApolloServerPluginUsageReporting,
+  ApolloServerPluginUsageReportingOptions,
+} from '../../../plugin/usageReporting';
+import { startStandaloneServer } from '../../../standalone';
+import { HeaderMap } from '../../../utils/HeaderMap';
+import { mockLogger } from '../../mockLogger';
+import { nockAfterEach, nockBeforeEach } from '../../nockAssertions';
+
+const mockReportingEndpoint = 'https://my-reporting-endpoint.com';
+
+describe('Error stats + `fieldLevelInstrumentation` (or non-ftv1 subgraphs)', () => {
+  beforeEach(nockBeforeEach);
+  afterEach(nockAfterEach);
+
+  it('fieldLevelInstrumentation disabled', async () => {
+    const logger = mockLogger();
+
+    const errorFtv1Subgraph = getErrorFtv1Subgraph(logger);
+    const errorFtv1SubgraphUrl = await startServer(errorFtv1Subgraph);
+
+    const errorNoFtv1Subgraph = getErrorNoFtv1Subgraph(logger);
+    const errorNoFtv1SubgraphUrl = await startServer(errorNoFtv1Subgraph);
+
+    const successSubgraph = getSuccessSubgraph(logger);
+    const successSubgraphUrl = await startServer(successSubgraph);
+
+    const gatewayServer = getGatewayServer(
+      [
+        { name: 'error-ftv1-subgraph', url: errorFtv1SubgraphUrl },
+        { name: 'error-no-ftv1-subgraph', url: errorNoFtv1SubgraphUrl },
+        { name: 'success-subgraph', url: successSubgraphUrl },
+      ],
+      logger,
+      {
+        fieldLevelInstrumentation: 0,
+      },
+    );
+    await startServer(gatewayServer);
+
+    nock(mockReportingEndpoint)
+      .post('/api/ingress/traces', (body) => {
+        const gzipReportBuffer = Buffer.from(body, 'hex');
+        const report = Report.decode(gunzipSync(gzipReportBuffer));
+        const statsKey = Object.keys(report.tracesPerQuery)[0];
+        const { queryLatencyStats, perTypeStat } = (
+          report.tracesPerQuery[statsKey]
+            ?.statsWithContext as IContextualizedStats[]
+        )[0];
+        expect(cleanLatencyCount(queryLatencyStats!)).toMatchInlineSnapshot(`
+          {
+            "cacheHits": 0,
+            "cacheLatencyCount": [],
+            "forbiddenOperationCount": 0,
+            "latencyCount": [
+              "*redacted for snapshot*",
+            ],
+            "persistedQueryHits": 0,
+            "persistedQueryMisses": 0,
+            "privateCacheTtlCount": [],
+            "publicCacheTtlCount": [],
+            "registeredOperationCount": 0,
+            "requestCount": 1,
+            "requestsWithErrorsCount": 1,
+            "requestsWithoutFieldInstrumentation": 1,
+            "rootErrorStats": {
+              "children": {
+                "service:error-ftv1-subgraph": {
+                  "children": {
+                    "errorFtv1": {
+                      "children": {},
+                      "errorsCount": 1,
+                      "requestsWithErrorsCount": 1,
+                    },
+                  },
+                  "errorsCount": 0,
+                  "requestsWithErrorsCount": 0,
+                },
+                "service:error-no-ftv1-subgraph": {
+                  "children": {
+                    "_entities": {
+                      "children": {
+                        "color": {
+                          "children": {
+                            "blueErrorNoFtv1": {
+                              "children": {},
+                              "errorsCount": 1,
+                              "requestsWithErrorsCount": 1,
+                            },
+                          },
+                          "errorsCount": 0,
+                          "requestsWithErrorsCount": 0,
+                        },
+                      },
+                      "errorsCount": 0,
+                      "requestsWithErrorsCount": 0,
+                    },
+                    "errorNoFtv1": {
+                      "children": {},
+                      "errorsCount": 1,
+                      "requestsWithErrorsCount": 1,
+                    },
+                    "productsWithErrorsNoFtv1": {
+                      "children": {
+                        "color": {
+                          "children": {
+                            "blueErrorNoFtv1": {
+                              "children": {},
+                              "errorsCount": 1,
+                              "requestsWithErrorsCount": 1,
+                            },
+                          },
+                          "errorsCount": 0,
+                          "requestsWithErrorsCount": 0,
+                        },
+                      },
+                      "errorsCount": 0,
+                      "requestsWithErrorsCount": 0,
+                    },
+                  },
+                  "errorsCount": 0,
+                  "requestsWithErrorsCount": 0,
+                },
+              },
+              "errorsCount": 0,
+              "requestsWithErrorsCount": 0,
+            },
+          }
+        `);
+        expect(perTypeStat).toMatchInlineSnapshot(`{}`);
+
+        return true;
+      })
+      .reply(200);
+
+    await gatewayServer.executeHTTPGraphQLRequest({
+      httpGraphQLRequest: {
+        method: 'POST',
+        headers: new HeaderMap([['content-type', 'application/json']]),
+        body: {
+          query: `{
+            errorFtv1
+            errorNoFtv1
+            productsWithErrorsNoFtv1 {
+              id
+              type
+              weight
+              color {
+                blueErrorNoFtv1
+                green
+                red
+              }
+            }
+            productsWithFtv1Errors {
+              id
+              type
+              weight
+              color {
+                blueErrorNoFtv1
+                green
+                red
+              }
+            }
+            success
+          }`,
+        },
+        search: '',
+      },
+      context: async () => ({}),
+    });
+
+    await gatewayServer.stop();
+    await errorFtv1Subgraph.stop();
+    await errorNoFtv1Subgraph.stop();
+    await successSubgraph.stop();
+  });
+
+  it('fieldLevelInstrumentation enabled', async () => {
+    const logger = mockLogger();
+
+    const errorFtv1Subgraph = getErrorFtv1Subgraph(logger);
+    const errorFtv1SubgraphUrl = await startServer(errorFtv1Subgraph);
+
+    const errorNoFtv1Subgraph = getErrorNoFtv1Subgraph(logger);
+    const errorNoFtv1SubgraphUrl = await startServer(errorNoFtv1Subgraph);
+
+    const successSubgraph = getSuccessSubgraph(logger);
+    const successSubgraphUrl = await startServer(successSubgraph);
+
+    const gatewayServer = getGatewayServer(
+      [
+        { name: 'error-ftv1-subgraph', url: errorFtv1SubgraphUrl },
+        { name: 'error-no-ftv1-subgraph', url: errorNoFtv1SubgraphUrl },
+        { name: 'success-subgraph', url: successSubgraphUrl },
+      ],
+      logger,
+      {
+        fieldLevelInstrumentation: 1,
+      },
+    );
+    await startServer(gatewayServer);
+
+    nock(mockReportingEndpoint)
+      .post('/api/ingress/traces', (body) => {
+        const gzipReportBuffer = Buffer.from(body, 'hex');
+        const report = Report.decode(gunzipSync(gzipReportBuffer));
+        const statsKey = Object.keys(report.tracesPerQuery)[0];
+        const { queryLatencyStats, perTypeStat } = (
+          report.tracesPerQuery[statsKey]
+            ?.statsWithContext as IContextualizedStats[]
+        )[0];
+
+        expect(cleanLatencyCount(queryLatencyStats!)).toMatchInlineSnapshot(`
+          {
+            "cacheHits": 0,
+            "cacheLatencyCount": [],
+            "forbiddenOperationCount": 0,
+            "latencyCount": [
+              "*redacted for snapshot*",
+            ],
+            "persistedQueryHits": 0,
+            "persistedQueryMisses": 0,
+            "privateCacheTtlCount": [],
+            "publicCacheTtlCount": [],
+            "registeredOperationCount": 0,
+            "requestCount": 1,
+            "requestsWithErrorsCount": 1,
+            "requestsWithoutFieldInstrumentation": 0,
+            "rootErrorStats": {
+              "children": {
+                "service:error-ftv1-subgraph": {
+                  "children": {
+                    "errorFtv1": {
+                      "children": {},
+                      "errorsCount": 1,
+                      "requestsWithErrorsCount": 1,
+                    },
+                  },
+                  "errorsCount": 0,
+                  "requestsWithErrorsCount": 0,
+                },
+                "service:error-no-ftv1-subgraph": {
+                  "children": {
+                    "_entities": {
+                      "children": {
+                        "color": {
+                          "children": {
+                            "blueErrorNoFtv1": {
+                              "children": {},
+                              "errorsCount": 1,
+                              "requestsWithErrorsCount": 1,
+                            },
+                          },
+                          "errorsCount": 0,
+                          "requestsWithErrorsCount": 0,
+                        },
+                      },
+                      "errorsCount": 0,
+                      "requestsWithErrorsCount": 0,
+                    },
+                    "errorNoFtv1": {
+                      "children": {},
+                      "errorsCount": 1,
+                      "requestsWithErrorsCount": 1,
+                    },
+                    "productsWithErrorsNoFtv1": {
+                      "children": {
+                        "color": {
+                          "children": {
+                            "blueErrorNoFtv1": {
+                              "children": {},
+                              "errorsCount": 1,
+                              "requestsWithErrorsCount": 1,
+                            },
+                          },
+                          "errorsCount": 0,
+                          "requestsWithErrorsCount": 0,
+                        },
+                      },
+                      "errorsCount": 0,
+                      "requestsWithErrorsCount": 0,
+                    },
+                  },
+                  "errorsCount": 0,
+                  "requestsWithErrorsCount": 0,
+                },
+              },
+              "errorsCount": 0,
+              "requestsWithErrorsCount": 0,
+            },
+          }
+        `);
+        expect(cleanLatencyCount(perTypeStat!)).toMatchInlineSnapshot(`
+          {
+            "Product": {
+              "perFieldStat": {
+                "id": {
+                  "errorsCount": 0,
+                  "estimatedExecutionCount": 1,
+                  "latencyCount": [
+                    "*redacted for snapshot*",
+                  ],
+                  "observedExecutionCount": 1,
+                  "requestsWithErrorsCount": 0,
+                  "returnType": "String!",
+                },
+                "type": {
+                  "errorsCount": 0,
+                  "estimatedExecutionCount": 1,
+                  "latencyCount": [
+                    "*redacted for snapshot*",
+                  ],
+                  "observedExecutionCount": 1,
+                  "requestsWithErrorsCount": 0,
+                  "returnType": "String!",
+                },
+              },
+            },
+            "Query": {
+              "perFieldStat": {
+                "errorFtv1": {
+                  "errorsCount": 1,
+                  "estimatedExecutionCount": 1,
+                  "latencyCount": [
+                    "*redacted for snapshot*",
+                  ],
+                  "observedExecutionCount": 1,
+                  "requestsWithErrorsCount": 1,
+                  "returnType": "String",
+                },
+                "productsWithFtv1Errors": {
+                  "errorsCount": 0,
+                  "estimatedExecutionCount": 1,
+                  "latencyCount": [
+                    "*redacted for snapshot*",
+                  ],
+                  "observedExecutionCount": 1,
+                  "requestsWithErrorsCount": 0,
+                  "returnType": "[Product!]!",
+                },
+                "success": {
+                  "errorsCount": 0,
+                  "estimatedExecutionCount": 1,
+                  "latencyCount": [
+                    "*redacted for snapshot*",
+                  ],
+                  "observedExecutionCount": 1,
+                  "requestsWithErrorsCount": 0,
+                  "returnType": "String",
+                },
+              },
+            },
+          }
+        `);
+
+        return true;
+      })
+      .reply(200);
+
+    await gatewayServer.executeHTTPGraphQLRequest({
+      httpGraphQLRequest: {
+        method: 'POST',
+        headers: new HeaderMap([['content-type', 'application/json']]),
+        body: {
+          query: `{
+          errorFtv1
+          errorNoFtv1
+          productsWithErrorsNoFtv1 {
+            id
+            type
+            weight
+            color {
+              blueErrorNoFtv1
+              green
+              red
+            }
+          }
+          productsWithFtv1Errors {
+            id
+            type
+            weight
+            color {
+              blueErrorNoFtv1
+              green
+              red
+            }
+          }
+          success
+        }`,
+        },
+        search: '',
+      },
+      context: async () => ({}),
+    });
+
+    await gatewayServer.stop();
+    await errorFtv1Subgraph.stop();
+    await errorNoFtv1Subgraph.stop();
+    await successSubgraph.stop();
+  });
+});
+
+function getErrorNoFtv1Subgraph(logger: Logger) {
+  const subgraphServer = new ApolloServer<BaseContext>({
+    schema: buildSubgraphSchema([
+      {
+        typeDefs: gql`
+          type Query {
+            errorNoFtv1: String
+            productsWithErrorsNoFtv1: [Product!]!
+          }
+
+          type Product @key(fields: "id") {
+            id: String!
+            weight: Float!
+            color: Color!
+          }
+
+          type Color {
+            red: Float!
+            green: Float!
+            blueErrorNoFtv1: Float!
+          }
+        `,
+        resolvers: {
+          Query: {
+            errorNoFtv1: () => {
+              throw new Error('errorNoFtv1');
+            },
+            productsWithErrorsNoFtv1: () => {
+              return [{ id: '1' }];
+            },
+          },
+          Product: {
+            id: () => '1',
+            weight: () => 2,
+            color: () => {
+              return {};
+            },
+            __resolveReference() {
+              return { id: '1' };
+            },
+          },
+          Color: {
+            red: () => 255,
+            green: () => 255,
+            blueErrorNoFtv1: () => {
+              throw new Error('Color.blue no ftv1 error');
+            },
+          },
+        },
+      },
+    ]),
+    plugins: [
+      ApolloServerPluginUsageReportingDisabled(),
+      {
+        // simulate a subgraph that ignores the header by just deleting it
+        // from the request before the inline trace plugin sees it
+        async requestDidStart({ request }) {
+          request.http?.headers.delete('apollo-federation-include-trace');
+        },
+      },
+    ],
+    logger,
+  });
+
+  return subgraphServer;
+}
+
+function getErrorFtv1Subgraph(logger: Logger) {
+  const subgraphServer = new ApolloServer<BaseContext>({
+    schema: buildSubgraphSchema([
+      {
+        typeDefs: gql`
+          type Query {
+            errorFtv1: String
+            productsWithFtv1Errors: [Product!]!
+          }
+
+          type Product @key(fields: "id") {
+            id: String!
+            type: String!
+          }
+        `,
+        resolvers: {
+          Query: {
+            errorFtv1: () => {
+              throw new Error('errorFtv1');
+            },
+            productsWithFtv1Errors: () => [{ id: '1' }],
+          },
+          Product: {
+            id: () => '1',
+            type: () => 'consumable',
+            __resolveReference() {
+              return { id: '1' };
+            },
+          },
+        },
+      },
+    ]),
+    plugins: [ApolloServerPluginUsageReportingDisabled()],
+    logger,
+  });
+
+  return subgraphServer;
+}
+
+function getSuccessSubgraph(logger: Logger) {
+  const subgraphServer = new ApolloServer<BaseContext>({
+    schema: buildSubgraphSchema([
+      {
+        typeDefs: gql`
+          #graphql
+          type Query {
+            success: String
+          }
+        `,
+        resolvers: {
+          Query: {
+            success: () => {
+              return 'success!';
+            },
+          },
+        },
+      },
+    ]),
+    plugins: [ApolloServerPluginUsageReportingDisabled()],
+    logger,
+  });
+
+  return subgraphServer;
+}
+
+function getGatewayServer(
+  subgraphs: ServiceEndpointDefinition[],
+  logger: Logger,
+  usageReportingConfig?: ApolloServerPluginUsageReportingOptions<BaseContext>,
+) {
+  return new ApolloServer({
+    gateway: new ApolloGateway({
+      supergraphSdl: new IntrospectAndCompose({
+        subgraphs,
+      }),
+      logger,
+    }),
+    apollo: { key: 'my-apollo-key', graphRef: 'my-graph@current' },
+    logger,
+    plugins: [
+      ApolloServerPluginUsageReporting({
+        endpointUrl: mockReportingEndpoint,
+        experimental_sendOperationAsTrace: () => false,
+        ...usageReportingConfig,
+      }),
+    ],
+  });
+}
+
+async function startServer(server: ApolloServer) {
+  const { url } = await startStandaloneServer(server, {
+    listen: { port: 0 },
+  });
+  return url;
+}
+
+function cleanLatencyCount(objOrArray: Record<string, any> | any[]): any {
+  if (Array.isArray(objOrArray)) {
+    return objOrArray.map(cleanLatencyCount);
+  }
+
+  if (typeof objOrArray === 'object') {
+    return Object.fromEntries(
+      Object.entries(objOrArray).map(([key, value]) => {
+        if (key === 'latencyCount') {
+          return ['latencyCount', ['*redacted for snapshot*']];
+        }
+        return [key, cleanLatencyCount(value)];
+      }),
+    );
+  }
+
+  return objOrArray;
+}