diff -pruN 1.6.0-1/.github/workflows/go.yml 1.7.0-1/.github/workflows/go.yml
--- 1.6.0-1/.github/workflows/go.yml	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/.github/workflows/go.yml	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,35 @@
+# This workflow will build a golang project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go
+name: Go
+
+on:
+  push:
+    branches: [ "master" ]
+  pull_request:
+    branches: [ "master" ]
+
+permissions:
+  contents: read
+  pull-requests: read
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v4
+
+    - name: Set up Go
+      uses: actions/setup-go@v5
+      with:
+        go-version: 1.24
+
+    - name: Build
+      run: go build -v ./...
+
+    - name: Test
+      run: go test -v ./...
+
+    - name: golangci-lint
+      uses: golangci/golangci-lint-action@v8
+      with:
+          version: v2.1.6
diff -pruN 1.6.0-1/.golangci.yml 1.7.0-1/.golangci.yml
--- 1.6.0-1/.golangci.yml	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/.golangci.yml	2025-08-19 13:15:23.000000000 +0000
@@ -1,32 +1,35 @@
+version: "2"
+
 run:
   timeout: 5m
 
-linters-settings:
-  gofmt:
-    simplify: true
-  govet:
-    check-shadowing: true
-    enable-all: true
-    disable:
-      - fieldalignment
-      - deepequalerrors # remove later
+formatters:
+  enable:
+    - gofmt
+    - goimports
+    - gofumpt
+  settings:
+    gofmt:
+      simplify: true
 
 linters:
-  disable-all: true
+  default: none
   enable:
-    - gofmt
-    - gosimple
     - govet
     - ineffassign
-    - exportloopref
     - staticcheck
     - unconvert
     - unused
     - misspell
-    - goimports
 
-issues:
-  exclude-rules:
-    - linters:
-      - unused
-      path: "graphql_test.go"
\ No newline at end of file
+  settings:
+    govet:
+      enable-all: true
+      disable:
+        - fieldalignment
+        - deepequalerrors # remove later
+      enable:
+        - shadow
+    unconvert:
+      fast-math: false
+      safe: false
diff -pruN 1.6.0-1/.semaphore/semaphore.yml 1.7.0-1/.semaphore/semaphore.yml
--- 1.6.0-1/.semaphore/semaphore.yml	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/.semaphore/semaphore.yml	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-version: v1.0
-name: Go
-agent:
-  machine:
-    type: e1-standard-2
-    os_image: ubuntu2004
-blocks:
-  - name: Style Check
-    task:
-      jobs:
-        - name: fmt
-          commands:
-            - sem-version go 1.20
-            - checkout
-            - ./scripts/golangci_install.sh -b $(go env GOPATH)/bin v1.51.0
-            - export PATH=$(go env GOPATH)/bin:$PATH
-            - golangci-lint run ./...
-
-  - name: Test & Build
-    task:
-      prologue:
-        commands:
-          - sem-version go 1.20
-          - export PATH=$(go env GOPATH)/bin:$PATH
-          - checkout
-          - go version
-
-      jobs:
-        - name: Test
-          commands:
-            - go test ./...
-
-        - name: Build
-          commands:
-            - go build -v .
diff -pruN 1.6.0-1/CHANGELOG.md 1.7.0-1/CHANGELOG.md
--- 1.6.0-1/CHANGELOG.md	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/CHANGELOG.md	2025-08-19 13:15:23.000000000 +0000
@@ -1,6 +1,11 @@
-CHANGELOG
+# CHANGELOG
+
+[v1.7.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.7.0) Release v1.7.0
+
+* [FEATURE] Add resolver field selection inspection helpers (`SelectedFieldNames`, `HasSelectedField`, `SortedSelectedFieldNames`). Helpers are available by default and compute results lazily only when called. An explicit opt-out (`DisableFieldSelections()` schema option) is provided for applications that want to remove even the minimal context insertion overhead when the helpers are never used.
 
 [v1.5.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.5.0) Release v1.5.0
+
 * [FEATURE] Add specifiedBy directive in #532
 * [IMPROVEMENT] In this release we improve validation for primitive values, directives, repeat directives, #515, #516, #525, #527
 * [IMPROVEMENT] Fix minor unreachable code caused by t.Fatalf #530
@@ -8,28 +13,27 @@ CHANGELOG
 * [BUG] Allow deprecated directive on arguments by @pavelnikolov in #541
 * [DOCS] Add array input example #536
 
-
 [v1.4.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.4.0) Release v1.4.0
-* [FEATURE] Add basic first step for Apollo Federation. This does NOT include full subgraph specification. This PR adds support only for `_service` schema level field. This library is long way from supporting the full sub-graph spec and we do not plan to implement that any time soon.
 
+* [FEATURE] Add basic first step for Apollo Federation. This does NOT include full subgraph specification. This PR adds support only for `_service` schema level field. This library is long way from supporting the full sub-graph spec and we do not plan to implement that any time soon.
 
 [v1.3.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.3.0) Release v1.3.0
+
 * [FEATURE] Support custom panic handler #468
 * [FEATURE] Support interfaces implementing interfaces #471
 * [BUG] Support parsing nanoseconds time properly #486
 * [BUG] Fix a bug in maxDepth fragment spread logic #492
 
-
 [v1.2.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.2.0) Release v1.2.0
-* [DOCS] Added examples of how to add JSON map as input scalar type. The goal of this change was to improve documentation #467
 
+* [DOCS] Added examples of how to add JSON map as input scalar type. The goal of this change was to improve documentation #467
 
 [v1.1.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.1.0) Release v1.1.0
+
 * [FEATURE] Add types package #437
 * [FEATURE] Expose `packer.Unmarshaler` as `decode.Unmarshaler` to the public #450
 * [FEATURE] Add location fields to type definitions #454 
 * [FEATURE] `errors.Errorf` preserves original error similar to `fmt.Errorf` #456
 * [BUGFIX] Fix duplicated __typename in response (fixes #369) #443
 
-
 [v1.0.0](https://github.com/graph-gophers/graphql-go/releases/tag/v1.0.0) Initial release
diff -pruN 1.6.0-1/CODE_OF_CONDUCT.md 1.7.0-1/CODE_OF_CONDUCT.md
--- 1.6.0-1/CODE_OF_CONDUCT.md	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/CODE_OF_CONDUCT.md	2025-08-19 13:15:23.000000000 +0000
@@ -1,6 +1,6 @@
-## Community Code of Conduct
+# Community Code of Conduct
 
-### Contributor Code of Conduct
+## Contributor Code of Conduct
 
 As contributors and maintainers of this project, and in the interest of fostering
 an open and welcoming community, we pledge to respect all people who contribute
@@ -9,7 +9,7 @@ submitting pull requests or patches, and
 
 We are committed to making participation in the GraphQL Go community a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
 
-## Scope 
+## Scope
 
 This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
 
@@ -36,17 +36,17 @@ Examples of unacceptable behavior includ
 * Other conduct which could reasonably be considered inappropriate in a
   professional setting
 
-Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. 
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct.
 By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect
-of managing this project. 
+of managing this project.
 Project maintainers who do not follow or enforce the Code of
 Conduct may be permanently removed from the project team.
 
-## Reporting 
+## Reporting
 
 For incidents occurring in the Graph Gophers community, contact @pavelnikolov in [the Gophers Slack](https://gophers.slack.com/) or alternatively you can contact  me [at] pavelnikolov [dot] net. You can expect a response within few business days.
 
-## Enforcement 
+## Enforcement
 
 The Graph Gophers maintainers enforce code of conduct issues for the graphql-go project as well other projects under the graph-gophers github organization.
 
diff -pruN 1.6.0-1/CONTRIBUTING.md 1.7.0-1/CONTRIBUTING.md
--- 1.6.0-1/CONTRIBUTING.md	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/CONTRIBUTING.md	2025-08-19 13:15:23.000000000 +0000
@@ -1,4 +1,4 @@
-## Contributing 
+# Contributing
 
 - With issues:
   - Use the search tool before opening a new issue.
@@ -11,7 +11,7 @@
   - It should pass all tests in the available continuous integrations systems such as TravisCI.
   - You should add/modify tests to cover your proposed code changes.
   - If your pull request contains a new feature, please document it well:
-    * Consider adding Go executable examples
-    * Comment all new exported types if outside of the `internal` package
-    * (optional) Mention it in the README
-    * Add a comment in the CHANGELOG.md explaining your feature
+    - Consider adding Go executable examples
+    - Comment all new exported types if outside of the `internal` package
+    - (optional) Mention it in the README
+    - Add a comment in the CHANGELOG.md explaining your feature
diff -pruN 1.6.0-1/README.md 1.7.0-1/README.md
--- 1.6.0-1/README.md	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/README.md	2025-08-19 13:15:23.000000000 +0000
@@ -1,4 +1,4 @@
-# graphql-go [![Sourcegraph](https://sourcegraph.com/github.com/graph-gophers/graphql-go/-/badge.svg)](https://sourcegraph.com/github.com/graph-gophers/graphql-go?badge) [![Build Status](https://graph-gophers.semaphoreci.com/badges/graphql-go/branches/master.svg?style=shields)](https://graph-gophers.semaphoreci.com/projects/graphql-go) [![Go Report](https://goreportcard.com/badge/github.com/graph-gophers/graphql-go)](https://goreportcard.com/report/github.com/graph-gophers/graphql-go) [![GoDoc](https://godoc.org/github.com/graph-gophers/graphql-go?status.svg)](https://godoc.org/github.com/graph-gophers/graphql-go)
+# graphql-go [![Sourcegraph](https://sourcegraph.com/github.com/graph-gophers/graphql-go/-/badge.svg)](https://sourcegraph.com/github.com/graph-gophers/graphql-go?badge) [![Go](https://github.com/graph-gophers/graphql-go/actions/workflows/go.yml/badge.svg)](https://github.com/graph-gophers/graphql-go/actions/workflows/go.yml) [![Go Report](https://goreportcard.com/badge/github.com/graph-gophers/graphql-go)](https://goreportcard.com/report/github.com/graph-gophers/graphql-go) [![GoDoc](https://godoc.org/github.com/graph-gophers/graphql-go?status.svg)](https://godoc.org/github.com/graph-gophers/graphql-go)
 
 <p align="center"><img src="docs/img/logo.png" width="300"></p>
 
@@ -156,6 +156,23 @@ schema := graphql.MustParseSchema(sdl, &
 - `Logger(logger log.Logger)` is used to log panics during query execution. It defaults to `exec.DefaultLogger`.
 - `PanicHandler(panicHandler errors.PanicHandler)` is used to transform panics into errors during query execution. It defaults to `errors.DefaultPanicHandler`.
 - `DisableIntrospection()` disables introspection queries.
+- `DisableFieldSelections()` disables capturing child field selections used by helper APIs (see below).
+
+### Field Selection Inspection Helpers
+
+Resolvers can introspect which immediate child fields were requested using:
+
+```go
+graphql.SelectedFieldNames(ctx)       // []string of direct child schema field names
+graphql.HasSelectedField(ctx, "name") // bool
+graphql.SortedSelectedFieldNames(ctx) // sorted copy
+```
+
+Use cases include building projection lists for databases or conditionally avoiding expensive sub-fetches. The helpers are intentionally shallow (only direct children) and fragment spreads / inline fragments are flattened with duplicates removed; meta fields (e.g. `__typename`) are excluded.
+
+Performance: selection data is computed lazily only when a helper is called. If you never call them there is effectively no additional overhead. To remove even the small context value insertion you can opt out with `DisableFieldSelections()`; helpers then return empty results.
+
+For more detail and examples see the [docs](https://godoc.org/github.com/graph-gophers/graphql-go).
 
 ### Custom Errors
 
diff -pruN 1.6.0-1/debian/changelog 1.7.0-1/debian/changelog
--- 1.6.0-1/debian/changelog	2025-03-21 23:03:23.000000000 +0000
+++ 1.7.0-1/debian/changelog	2025-08-25 13:50:55.000000000 +0000
@@ -1,3 +1,10 @@
+golang-github-graph-gophers-graphql-go (1.7.0-1) unstable; urgency=medium
+
+  * Change to new packaging repo layout based on upstream Git.
+  * New upstream release.
+
+ -- Sascha Steinbiss <satta@debian.org>  Mon, 25 Aug 2025 15:50:55 +0200
+
 golang-github-graph-gophers-graphql-go (1.6.0-1) unstable; urgency=medium
 
   * New upstream release.
diff -pruN 1.6.0-1/debian/gbp.conf 1.7.0-1/debian/gbp.conf
--- 1.6.0-1/debian/gbp.conf	2025-03-21 23:01:45.000000000 +0000
+++ 1.7.0-1/debian/gbp.conf	2025-08-25 13:50:55.000000000 +0000
@@ -1,2 +1 @@
 [DEFAULT]
-pristine-tar = True
diff -pruN 1.6.0-1/example/federation/integration/gateway/package-lock.json 1.7.0-1/example/federation/integration/gateway/package-lock.json
--- 1.6.0-1/example/federation/integration/gateway/package-lock.json	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/example/federation/integration/gateway/package-lock.json	2025-08-19 13:15:23.000000000 +0000
@@ -1,14 +1,14 @@
 {
   "name": "apollo-federation-gateway",
-  "version": "1.0.1",
+  "version": "1.1.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "apollo-federation-gateway",
-      "version": "1.0.1",
+      "version": "1.1.0",
       "dependencies": {
-        "@apollo/gateway": "^2.10.0",
+        "@apollo/gateway": "^2.10.1",
         "@apollo/server": "^4.11.3",
         "graphql": "^16.10.0"
       }
@@ -21,44 +21,14 @@
         "graphql": "14.x || 15.x || 16.x"
       }
     },
-    "node_modules/@apollo/gateway": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/gateway/-/gateway-2.10.0.tgz",
-      "integrity": "sha512-XJdyCpUr1G309j8tkHkkaG/KhHDD44/NbxwEF0d8CBMp+DHyYl8fgojUogSmiVJ/Ggdg9/68U4RznojbvCqBCw==",
-      "dependencies": {
-        "@apollo/composition": "2.10.0",
-        "@apollo/federation-internals": "2.10.0",
-        "@apollo/query-planner": "2.10.0",
-        "@apollo/server-gateway-interface": "^1.1.0",
-        "@apollo/usage-reporting-protobuf": "^4.1.0",
-        "@apollo/utils.createhash": "^2.0.0",
-        "@apollo/utils.fetcher": "^2.0.0",
-        "@apollo/utils.isnodelike": "^2.0.0",
-        "@apollo/utils.keyvaluecache": "^2.1.0",
-        "@apollo/utils.logger": "^2.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",
-        "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/composition": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/composition/-/composition-2.10.0.tgz",
-      "integrity": "sha512-+EkUY97+DMrBnMvbaPGwYwVmOzNgvAmbvRJSMGGC95ISnev7Cd5sVVVP6HKKann3hd8Yq6y83Enzp1xew5HI4w==",
+    "node_modules/@apollo/composition": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/@apollo/composition/-/composition-2.10.1.tgz",
+      "integrity": "sha512-plQwaoemEuL7rDjb51ULmxJmstaoBK9ys/HvGMUtTXTxSIM1COkMK29x7fGHrztwdfDiGqEN4H+JGZeraBZHAg==",
+      "license": "Elastic-2.0",
       "dependencies": {
-        "@apollo/federation-internals": "2.10.0",
-        "@apollo/query-graphs": "2.10.0"
+        "@apollo/federation-internals": "2.10.1",
+        "@apollo/query-graphs": "2.10.1"
       },
       "engines": {
         "node": ">=14.15.0"
@@ -67,27 +37,11 @@
         "graphql": "^16.5.0"
       }
     },
-    "node_modules/@apollo/gateway/node_modules/@apollo/composition/node_modules/@apollo/query-graphs": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/query-graphs/-/query-graphs-2.10.0.tgz",
-      "integrity": "sha512-d9PgQ7sjd98lK2NvKKYp1iOZP24OrvbtRw5GNuW7nlQPYD4D8DCofEBGtDXs7RIcWaMp5OrU4U2dQcCzPi2MDg==",
-      "dependencies": {
-        "@apollo/federation-internals": "2.10.0",
-        "deep-equal": "^2.0.5",
-        "ts-graphviz": "^1.5.4",
-        "uuid": "^9.0.0"
-      },
-      "engines": {
-        "node": ">=14.15.0"
-      },
-      "peerDependencies": {
-        "graphql": "^16.5.0"
-      }
-    },
-    "node_modules/@apollo/gateway/node_modules/@apollo/federation-internals": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/federation-internals/-/federation-internals-2.10.0.tgz",
-      "integrity": "sha512-IneWuwDc9ozKLcEsKw7YEkhzo7VAa54RjKwAVEqPFHPVqUjIYUKX99gSWAp9ZQeI8DGrz2a8uKEDlKGOHh3UaA==",
+    "node_modules/@apollo/federation-internals": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/@apollo/federation-internals/-/federation-internals-2.10.1.tgz",
+      "integrity": "sha512-QToNlspkpA/qXOMwdIUzmJe3OasZFpSO92luQik6Ov9aJBnxldLGPi6rD0FkunVd678lHuKWDFQ4vkb7/KCfgg==",
+      "license": "Elastic-2.0",
       "dependencies": {
         "@types/uuid": "^9.0.0",
         "chalk": "^4.1.0",
@@ -101,34 +55,30 @@
         "graphql": "^16.5.0"
       }
     },
-    "node_modules/@apollo/gateway/node_modules/@apollo/query-planner": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/query-planner/-/query-planner-2.10.0.tgz",
-      "integrity": "sha512-vt+UaHbH1Jyc1Xi04XXnDrQFBwL/T/7cJC/13zuAZUnge5oN6udfc3wa/MeSxri8a1pV+c8us3dwlnAAsp7vvw==",
-      "dependencies": {
-        "@apollo/federation-internals": "2.10.0",
-        "@apollo/query-graphs": "2.10.0",
+    "node_modules/@apollo/gateway": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/@apollo/gateway/-/gateway-2.10.1.tgz",
+      "integrity": "sha512-MFU41xHK3KUOpw4+PlJxeFxxSajoO39Pm9jeIjAG8TtXAmIJHdqXWnM3eHJ2LZkqfZ99L8L5ZCkDygvgisO9NA==",
+      "license": "Elastic-2.0",
+      "dependencies": {
+        "@apollo/composition": "2.10.1",
+        "@apollo/federation-internals": "2.10.1",
+        "@apollo/query-planner": "2.10.1",
+        "@apollo/server-gateway-interface": "^1.1.0",
+        "@apollo/usage-reporting-protobuf": "^4.1.0",
+        "@apollo/utils.createhash": "^2.0.0",
+        "@apollo/utils.fetcher": "^2.0.0",
+        "@apollo/utils.isnodelike": "^2.0.0",
         "@apollo/utils.keyvaluecache": "^2.1.0",
-        "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/gateway/node_modules/@apollo/query-planner/node_modules/@apollo/query-graphs": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@apollo/query-graphs/-/query-graphs-2.10.0.tgz",
-      "integrity": "sha512-d9PgQ7sjd98lK2NvKKYp1iOZP24OrvbtRw5GNuW7nlQPYD4D8DCofEBGtDXs7RIcWaMp5OrU4U2dQcCzPi2MDg==",
-      "dependencies": {
-        "@apollo/federation-internals": "2.10.0",
-        "deep-equal": "^2.0.5",
-        "ts-graphviz": "^1.5.4",
-        "uuid": "^9.0.0"
+        "@apollo/utils.logger": "^2.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",
+        "make-fetch-happen": "^11.0.0",
+        "node-abort-controller": "^3.0.1",
+        "node-fetch": "^2.6.7"
       },
       "engines": {
         "node": ">=14.15.0"
@@ -161,6 +111,44 @@
         "apollo-pbts": "bin/pbts"
       }
     },
+    "node_modules/@apollo/query-graphs": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-graphs/-/query-graphs-2.10.1.tgz",
+      "integrity": "sha512-nJMujPDmmkPqZcHYIa8pe738uknFEyldYGQj2cljj/mhuL7lmF3oNS4xsdjes16v3cIAngBYzPkPJfRTf57yPg==",
+      "license": "Elastic-2.0",
+      "dependencies": {
+        "@apollo/federation-internals": "2.10.1",
+        "deep-equal": "^2.0.5",
+        "ts-graphviz": "^1.5.4",
+        "uuid": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=14.15.0"
+      },
+      "peerDependencies": {
+        "graphql": "^16.5.0"
+      }
+    },
+    "node_modules/@apollo/query-planner": {
+      "version": "2.10.1",
+      "resolved": "https://registry.npmjs.org/@apollo/query-planner/-/query-planner-2.10.1.tgz",
+      "integrity": "sha512-DPBI/+K0Qw5jS8Y+vJDnTYl40fPIuoWT6/4VQEXtfI1Dskvw0HrfgeGLmdOZHI8R07A9/DGQZr/V7AdQTWIwzg==",
+      "license": "Elastic-2.0",
+      "dependencies": {
+        "@apollo/federation-internals": "2.10.1",
+        "@apollo/query-graphs": "2.10.1",
+        "@apollo/utils.keyvaluecache": "^2.1.0",
+        "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": {
       "version": "4.11.3",
       "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.11.3.tgz",
@@ -419,6 +407,7 @@
       "version": "29.6.3",
       "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
       "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+      "license": "MIT",
       "dependencies": {
         "@sinclair/typebox": "^0.27.8"
       },
@@ -516,7 +505,8 @@
     "node_modules/@sinclair/typebox": {
       "version": "0.27.8",
       "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
-      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
+      "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+      "license": "MIT"
     },
     "node_modules/@tootallnate/once": {
       "version": "2.0.0",
@@ -626,7 +616,8 @@
     "node_modules/@types/uuid": {
       "version": "9.0.8",
       "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
-      "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
+      "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
+      "license": "MIT"
     },
     "node_modules/accepts": {
       "version": "1.3.8",
@@ -724,6 +715,7 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
       "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+      "license": "MIT",
       "dependencies": {
         "call-bound": "^1.0.3",
         "is-array-buffer": "^3.0.5"
@@ -757,6 +749,7 @@
       "version": "1.0.7",
       "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
       "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+      "license": "MIT",
       "dependencies": {
         "possible-typed-array-names": "^1.0.0"
       },
@@ -796,9 +789,10 @@
       }
     },
     "node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+      "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+      "license": "MIT",
       "dependencies": {
         "balanced-match": "^1.0.0"
       }
@@ -845,6 +839,7 @@
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
       "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+      "license": "MIT",
       "dependencies": {
         "call-bind-apply-helpers": "^1.0.0",
         "es-define-property": "^1.0.0",
@@ -871,12 +866,13 @@
       }
     },
     "node_modules/call-bound": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
-      "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind-apply-helpers": "^1.0.1",
-        "get-intrinsic": "^1.2.6"
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
       },
       "engines": {
         "node": ">= 0.4"
@@ -889,6 +885,7 @@
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
       "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "license": "MIT",
       "dependencies": {
         "ansi-styles": "^4.1.0",
         "supports-color": "^7.1.0"
@@ -1012,6 +1009,7 @@
       "version": "2.2.3",
       "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
       "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
+      "license": "MIT",
       "dependencies": {
         "array-buffer-byte-length": "^1.0.0",
         "call-bind": "^1.0.5",
@@ -1043,6 +1041,7 @@
       "version": "1.1.4",
       "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
       "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+      "license": "MIT",
       "dependencies": {
         "es-define-property": "^1.0.0",
         "es-errors": "^1.3.0",
@@ -1059,6 +1058,7 @@
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
       "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+      "license": "MIT",
       "dependencies": {
         "define-data-property": "^1.0.1",
         "has-property-descriptors": "^1.0.0",
@@ -1178,6 +1178,7 @@
       "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==",
+      "license": "MIT",
       "dependencies": {
         "call-bind": "^1.0.2",
         "get-intrinsic": "^1.1.3",
@@ -1294,11 +1295,18 @@
       }
     },
     "node_modules/for-each": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
-      "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+      "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+      "license": "MIT",
       "dependencies": {
-        "is-callable": "^1.1.3"
+        "is-callable": "^1.2.7"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/foreground-child": {
@@ -1317,13 +1325,15 @@
       }
     },
     "node_modules/form-data": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
-      "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
+      "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
+      "license": "MIT",
       "dependencies": {
         "asynckit": "^0.4.0",
         "combined-stream": "^1.0.8",
         "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
         "mime-types": "^2.1.12"
       },
       "engines": {
@@ -1377,21 +1387,23 @@
       "version": "1.2.3",
       "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
       "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+      "license": "MIT",
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/get-intrinsic": {
-      "version": "1.2.7",
-      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
-      "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind-apply-helpers": "^1.0.1",
+        "call-bind-apply-helpers": "^1.0.2",
         "es-define-property": "^1.0.1",
         "es-errors": "^1.3.0",
-        "es-object-atoms": "^1.0.0",
+        "es-object-atoms": "^1.1.1",
         "function-bind": "^1.1.2",
-        "get-proto": "^1.0.0",
+        "get-proto": "^1.0.1",
         "gopd": "^1.2.0",
         "has-symbols": "^1.1.0",
         "hasown": "^2.0.2",
@@ -1463,9 +1475,13 @@
       }
     },
     "node_modules/has-bigints": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
-      "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+      "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
@@ -1474,6 +1490,7 @@
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
       "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "license": "MIT",
       "engines": {
         "node": ">=8"
       }
@@ -1482,6 +1499,7 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
       "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+      "license": "MIT",
       "dependencies": {
         "es-define-property": "^1.0.0"
       },
@@ -1656,6 +1674,7 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
       "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+      "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0",
         "hasown": "^2.0.2",
@@ -1689,6 +1708,7 @@
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
       "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
+      "license": "MIT",
       "dependencies": {
         "call-bound": "^1.0.2",
         "has-tostringtag": "^1.0.2"
@@ -1704,6 +1724,7 @@
       "version": "3.0.5",
       "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
       "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+      "license": "MIT",
       "dependencies": {
         "call-bind": "^1.0.8",
         "call-bound": "^1.0.3",
@@ -1717,23 +1738,28 @@
       }
     },
     "node_modules/is-bigint": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
-      "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+      "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+      "license": "MIT",
       "dependencies": {
-        "has-bigints": "^1.0.1"
+        "has-bigints": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/is-boolean-object": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
-      "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+      "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "has-tostringtag": "^1.0.0"
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1746,6 +1772,7 @@
       "version": "1.2.7",
       "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
       "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       },
@@ -1754,11 +1781,13 @@
       }
     },
     "node_modules/is-date-object": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
-      "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+      "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+      "license": "MIT",
       "dependencies": {
-        "has-tostringtag": "^1.0.0"
+        "call-bound": "^1.0.2",
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1784,6 +1813,7 @@
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
       "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       },
@@ -1792,11 +1822,13 @@
       }
     },
     "node_modules/is-number-object": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
-      "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+      "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+      "license": "MIT",
       "dependencies": {
-        "has-tostringtag": "^1.0.0"
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1806,12 +1838,15 @@
       }
     },
     "node_modules/is-regex": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
-      "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+      "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "has-tostringtag": "^1.0.0"
+        "call-bound": "^1.0.2",
+        "gopd": "^1.2.0",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1824,6 +1859,7 @@
       "version": "2.0.3",
       "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
       "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       },
@@ -1832,22 +1868,28 @@
       }
     },
     "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",
-      "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+      "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind": "^1.0.2"
+        "call-bound": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/is-string": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
-      "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+      "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+      "license": "MIT",
       "dependencies": {
-        "has-tostringtag": "^1.0.0"
+        "call-bound": "^1.0.3",
+        "has-tostringtag": "^1.0.2"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1857,11 +1899,14 @@
       }
     },
     "node_modules/is-symbol": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
-      "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+      "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+      "license": "MIT",
       "dependencies": {
-        "has-symbols": "^1.0.2"
+        "call-bound": "^1.0.2",
+        "has-symbols": "^1.1.0",
+        "safe-regex-test": "^1.1.0"
       },
       "engines": {
         "node": ">= 0.4"
@@ -1874,6 +1919,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
       "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       },
@@ -1885,6 +1931,7 @@
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
       "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+      "license": "MIT",
       "dependencies": {
         "call-bound": "^1.0.3",
         "get-intrinsic": "^1.2.6"
@@ -1899,7 +1946,8 @@
     "node_modules/isarray": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
-      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+      "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+      "license": "MIT"
     },
     "node_modules/isexe": {
       "version": "2.0.0",
@@ -1924,6 +1972,7 @@
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
       "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
+      "license": "MIT",
       "engines": {
         "node": ">=0.10.0"
       }
@@ -2278,6 +2327,7 @@
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
       "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+      "license": "MIT",
       "dependencies": {
         "call-bind": "^1.0.7",
         "define-properties": "^1.2.1"
@@ -2293,18 +2343,22 @@
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
       "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       }
     },
     "node_modules/object.assign": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
-      "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+      "version": "4.1.7",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+      "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+      "license": "MIT",
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
-        "has-symbols": "^1.0.3",
+        "call-bind": "^1.0.8",
+        "call-bound": "^1.0.3",
+        "define-properties": "^1.2.1",
+        "es-object-atoms": "^1.0.0",
+        "has-symbols": "^1.1.0",
         "object-keys": "^1.1.1"
       },
       "engines": {
@@ -2389,6 +2443,7 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
       "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+      "license": "MIT",
       "engines": {
         "node": ">= 0.4"
       }
@@ -2397,6 +2452,7 @@
       "version": "29.7.0",
       "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
       "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+      "license": "MIT",
       "dependencies": {
         "@jest/schemas": "^29.6.3",
         "ansi-styles": "^5.0.0",
@@ -2410,6 +2466,7 @@
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
       "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+      "license": "MIT",
       "engines": {
         "node": ">=10"
       },
@@ -2488,12 +2545,14 @@
     "node_modules/react-is": {
       "version": "18.3.1",
       "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
-      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+      "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==",
+      "license": "MIT"
     },
     "node_modules/regexp.prototype.flags": {
       "version": "1.5.4",
       "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
       "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+      "license": "MIT",
       "dependencies": {
         "call-bind": "^1.0.8",
         "define-properties": "^1.2.1",
@@ -2536,6 +2595,23 @@
         }
       ]
     },
+    "node_modules/safe-regex-test": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+      "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "is-regex": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
     "node_modules/safer-buffer": {
       "version": "2.1.2",
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -2606,6 +2682,7 @@
       "version": "1.2.2",
       "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
       "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+      "license": "MIT",
       "dependencies": {
         "define-data-property": "^1.1.4",
         "es-errors": "^1.3.0",
@@ -2622,6 +2699,7 @@
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
       "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+      "license": "MIT",
       "dependencies": {
         "define-data-property": "^1.1.4",
         "es-errors": "^1.3.0",
@@ -2839,6 +2917,7 @@
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
       "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+      "license": "MIT",
       "dependencies": {
         "es-errors": "^1.3.0",
         "internal-slot": "^1.1.0"
@@ -2939,6 +3018,7 @@
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
       "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "license": "MIT",
       "dependencies": {
         "has-flag": "^4.0.0"
       },
@@ -3001,6 +3081,7 @@
       "version": "1.8.2",
       "resolved": "https://registry.npmjs.org/ts-graphviz/-/ts-graphviz-1.8.2.tgz",
       "integrity": "sha512-5YhbFoHmjxa7pgQLkB07MtGnGJ/yhvjmc9uhsnDBEICME6gkPf83SBwLDQqGDoCa3XzUMWLk1AU2Wn1u1naDtA==",
+      "license": "MIT",
       "engines": {
         "node": ">=14.16"
       },
@@ -3129,15 +3210,19 @@
       }
     },
     "node_modules/which-boxed-primitive": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
-      "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
-      "dependencies": {
-        "is-bigint": "^1.0.1",
-        "is-boolean-object": "^1.1.0",
-        "is-number-object": "^1.0.4",
-        "is-string": "^1.0.5",
-        "is-symbol": "^1.0.3"
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+      "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+      "license": "MIT",
+      "dependencies": {
+        "is-bigint": "^1.1.0",
+        "is-boolean-object": "^1.2.1",
+        "is-number-object": "^1.1.1",
+        "is-string": "^1.1.1",
+        "is-symbol": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
       },
       "funding": {
         "url": "https://github.com/sponsors/ljharb"
@@ -3147,6 +3232,7 @@
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
       "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+      "license": "MIT",
       "dependencies": {
         "is-map": "^2.0.3",
         "is-set": "^2.0.3",
@@ -3161,14 +3247,16 @@
       }
     },
     "node_modules/which-typed-array": {
-      "version": "1.1.18",
-      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz",
-      "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==",
+      "version": "1.1.19",
+      "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+      "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+      "license": "MIT",
       "dependencies": {
         "available-typed-arrays": "^1.0.7",
         "call-bind": "^1.0.8",
-        "call-bound": "^1.0.3",
-        "for-each": "^0.3.3",
+        "call-bound": "^1.0.4",
+        "for-each": "^0.3.5",
+        "get-proto": "^1.0.1",
         "gopd": "^1.2.0",
         "has-tostringtag": "^1.0.2"
       },
diff -pruN 1.6.0-1/example/federation/integration/gateway/package.json 1.7.0-1/example/federation/integration/gateway/package.json
--- 1.6.0-1/example/federation/integration/gateway/package.json	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/example/federation/integration/gateway/package.json	2025-08-19 13:15:23.000000000 +0000
@@ -8,7 +8,7 @@
     "start": "node index.js"
   },
   "dependencies": {
-    "@apollo/gateway": "^2.10.0",
+    "@apollo/gateway": "^2.10.1",
     "@apollo/server": "^4.11.3",
     "graphql": "^16.10.0"
   }
diff -pruN 1.6.0-1/example/social/social.go 1.7.0-1/example/social/social.go
--- 1.6.0-1/example/social/social.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/example/social/social.go	2025-08-19 13:15:23.000000000 +0000
@@ -202,7 +202,8 @@ type Resolver struct{}
 func (r *Resolver) Admin(ctx context.Context, args struct {
 	ID   string
 	Role string
-}) (*adminResolver, error) {
+},
+) (*adminResolver, error) {
 	if usr, ok := usersMap[args.ID]; ok {
 		if usr.RoleField == args.Role {
 			return &adminResolver{*usr}, nil
@@ -212,11 +213,11 @@ func (r *Resolver) Admin(ctx context.Con
 	return nil, err
 }
 
-func (r *Resolver) User(ctx context.Context, args struct{ Id string }) (user, error) {
-	if usr, ok := usersMap[args.Id]; ok {
+func (r *Resolver) User(ctx context.Context, args struct{ ID string }) (user, error) {
+	if usr, ok := usersMap[args.ID]; ok {
 		return *usr, nil
 	}
-	err := fmt.Errorf("user with id=%s does not exist", args.Id)
+	err := fmt.Errorf("user with id=%s does not exist", args.ID)
 	return user{}, err
 }
 
diff -pruN 1.6.0-1/example/starwars/starwars.go 1.7.0-1/example/starwars/starwars.go
--- 1.6.0-1/example/starwars/starwars.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/example/starwars/starwars.go	2025-08-19 13:15:23.000000000 +0000
@@ -367,7 +367,8 @@ type MutationResolver struct{}
 func (r *MutationResolver) CreateReview(args *struct {
 	Episode string
 	Review  reviewInput
-}) *reviewResolver {
+},
+) *reviewResolver {
 	review := &review{
 		stars:      args.Review.Stars,
 		commentary: args.Review.Commentary,
diff -pruN 1.6.0-1/example_custom_err_test.go 1.7.0-1/example_custom_err_test.go
--- 1.6.0-1/example_custom_err_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/example_custom_err_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -59,7 +59,7 @@ func (e productNotFoundError) Extensions
 
 // Example_customErrors demonstrates the use of custom errors and error extensions.
 func Example_customErrors() {
-	var products = []*product{
+	products := []*product{
 		{ID: "1000", Name: "Product1"},
 		{ID: "1001", Name: "Product2"},
 	}
diff -pruN 1.6.0-1/example_selection2_test.go 1.7.0-1/example_selection2_test.go
--- 1.6.0-1/example_selection2_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/example_selection2_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,49 @@
+package graphql_test
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/graph-gophers/graphql-go"
+)
+
+type (
+	user2         struct{ id, name, email string }
+	userResolver2 struct{ u user2 }
+)
+
+func (r *userResolver2) ID() graphql.ID                               { return graphql.ID(r.u.id) }
+func (r *userResolver2) Name() *string                                { return &r.u.name }
+func (r *userResolver2) Email() *string                               { return &r.u.email }
+func (r *userResolver2) Friends(ctx context.Context) []*userResolver2 { return nil }
+
+type root2 struct{}
+
+func (r *root2) User(ctx context.Context, args struct{ ID string }) *userResolver2 {
+	if graphql.HasSelectedField(ctx, "email") {
+		fmt.Println("email requested")
+	}
+	if graphql.HasSelectedField(ctx, "friends") {
+		fmt.Println("friends requested")
+	}
+	return &userResolver2{u: user2{id: args.ID, name: "Alice", email: "a@example.com"}}
+}
+
+// Example_hasSelectedField demonstrates HasSelectedField helper for conditional
+// logic without needing the full slice of field names. This can be handy when
+// checking for a small number of specific fields (avoids allocating the names
+// slice if it hasn't already been built).
+func Example_hasSelectedField() {
+	const s = `
+		schema { query: Query }
+		type Query { user(id: ID!): User }
+		type User { id: ID! name: String email: String friends: [User!]! }
+	`
+	schema := graphql.MustParseSchema(s, &root2{})
+	// Select a subset of fields including a nested composite field; friends requires its own selection set.
+	query := `query { user(id: "U1") { id email friends { id } } }`
+	_ = schema.Exec(context.Background(), query, "", nil)
+	// Output:
+	// email requested
+	// friends requested
+}
diff -pruN 1.6.0-1/example_selection_test.go 1.7.0-1/example_selection_test.go
--- 1.6.0-1/example_selection_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/example_selection_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,41 @@
+package graphql_test
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/graph-gophers/graphql-go"
+)
+
+type (
+	user         struct{ id, name, email string }
+	userResolver struct{ u user }
+)
+
+func (r *userResolver) ID() graphql.ID                              { return graphql.ID(r.u.id) }
+func (r *userResolver) Name() *string                               { return &r.u.name }
+func (r *userResolver) Email() *string                              { return &r.u.email }
+func (r *userResolver) Friends(ctx context.Context) []*userResolver { return nil }
+
+type root struct{}
+
+func (r *root) User(ctx context.Context, args struct{ ID string }) *userResolver {
+	fields := graphql.SelectedFieldNames(ctx)
+	fmt.Println(fields)
+	return &userResolver{u: user{id: args.ID, name: "Alice", email: "a@example.com"}}
+}
+
+// Example_selectedFieldNames demonstrates SelectedFieldNames usage in a resolver for
+// conditional data fetching (e.g. building a DB projection list).
+func Example_selectedFieldNames() {
+	const s = `
+        schema { query: Query }
+        type Query { user(id: ID!): User }
+        type User { id: ID! name: String email: String friends: [User!]! }
+    `
+	schema := graphql.MustParseSchema(s, &root{})
+	query := `query { user(id: "U1") { id name } }`
+	_ = schema.Exec(context.Background(), query, "", nil)
+	// Output:
+	// [id name]
+}
diff -pruN 1.6.0-1/examples_test.go 1.7.0-1/examples_test.go
--- 1.6.0-1/examples_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/examples_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -157,7 +157,8 @@ func ExampleMaxQueryLength() {
 }
 
 func ExampleRestrictIntrospection() {
-	allowKey := struct{}{}
+	type allowKeyType struct{}
+	allowKey := allowKeyType{}
 	// only allow introspection if the function below returns true
 	filter := func(ctx context.Context) bool {
 		allow, found := ctx.Value(allowKey).(bool)
diff -pruN 1.6.0-1/fuzz_test.go 1.7.0-1/fuzz_test.go
--- 1.6.0-1/fuzz_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/fuzz_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,55 @@
+package graphql_test
+
+import (
+	"context"
+	"testing"
+
+	"github.com/graph-gophers/graphql-go"
+	"github.com/graph-gophers/graphql-go/example/starwars"
+)
+
+func FuzzSchemaExec(f *testing.F) {
+	resolver := &starwars.Resolver{}
+	opts := []graphql.SchemaOpt{graphql.MaxDepth(3)}
+	schema, err := graphql.ParseSchema(starwars.Schema, resolver, opts...)
+	if err != nil {
+		f.Errorf("ParseSchema: %v", err)
+		return
+	}
+
+	// Seed the fuzzing corpus with a variety of valid GraphQL queries.
+	queries := []string{
+		`{ hero { name } }`,
+		`{ hero { name appearsIn } }`,
+		`{ hero { name appearsIn friends { name } } }`,
+		`{ hero(episode: EMPIRE) { name } }`,
+		`{ episode(episode: EMPIRE) { title characters { name } reviews { stars commentary } } }`,
+		`{ episode(episode: EMPIRE) { title characters { name friends { name } reviews { stars commentary } } }`,
+		`query { episode(episode: EMPIRE) { title characters { name friends { name } } } }`,
+		`query HeroName { hero { name } }`,
+		`query HeroNameAndFriends { hero { name friends { name } } }`,
+		`mutation { createReview(episode: EMPIRE, review: { stars: 5, commentary: "Great!" }) }`,
+	}
+	for _, q := range queries {
+		f.Add(q)
+	}
+
+	f.Fuzz(func(t *testing.T, query string) {
+		// ignore invalid queries in order to test only the execution against the schema
+		errs := schema.Validate(query)
+		if len(errs) > 0 {
+			t.Skip()
+		}
+
+		res := schema.Exec(context.Background(), query, "", nil)
+		if res.Data != nil && len(res.Errors) > 0 {
+			t.Errorf("Exec(%q) returned both data and errors: %v", query, res.Errors)
+		}
+		if res.Errors != nil {
+			t.Logf("Exec(%q) returned errors: %v", query, res.Errors)
+		}
+		if res.Data == nil && len(res.Errors) == 0 {
+			t.Errorf("Exec(%q) returned nil data and no errors", query)
+		}
+	})
+}
diff -pruN 1.6.0-1/graphql.go 1.7.0-1/graphql.go
--- 1.6.0-1/graphql.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/graphql.go	2025-08-19 13:15:23.000000000 +0000
@@ -85,6 +85,7 @@ type Schema struct {
 	useStringDescriptions    bool
 	subscribeResolverTimeout time.Duration
 	useFieldResolvers        bool
+	disableFieldSelections   bool
 }
 
 // AST returns the abstract syntax tree of the GraphQL schema definition.
@@ -121,6 +122,15 @@ func UseFieldResolvers() SchemaOpt {
 	}
 }
 
+// DisableFieldSelections disables capturing child field selections for the
+// SelectedFieldNames / HasSelectedField helpers. When disabled, those helpers
+// will always return an empty result / false (i.e. zero-value) and no per-resolver
+// selection context is stored. This is an opt-out for applications that never intend
+// to use the feature and want to avoid even its small lazy overhead.
+func DisableFieldSelections() SchemaOpt {
+	return func(s *Schema) { s.disableFieldSelections = true }
+}
+
 // MaxDepth specifies the maximum field nesting depth in a query. The default is 0 which disables max depth checking.
 func MaxDepth(n int) SchemaOpt {
 	return func(s *Schema) {
@@ -233,6 +243,10 @@ func (s *Schema) ValidateWithVariables(q
 		return []*errors.QueryError{qErr}
 	}
 
+	if len(doc.Operations) == 0 {
+		return []*errors.QueryError{errors.Errorf("executable document must contain at least one operation")}
+	}
+
 	return validation.Validate(s.schema, doc, variables, s.maxDepth)
 }
 
@@ -300,10 +314,11 @@ func (s *Schema) exec(ctx context.Contex
 			Schema:             s.schema,
 			AllowIntrospection: s.allowIntrospection == nil || s.allowIntrospection(ctx), // allow introspection by default, i.e. when allowIntrospection is nil
 		},
-		Limiter:      make(chan struct{}, s.maxParallelism),
-		Tracer:       s.tracer,
-		Logger:       s.logger,
-		PanicHandler: s.panicHandler,
+		Limiter:                make(chan struct{}, s.maxParallelism),
+		Tracer:                 s.tracer,
+		Logger:                 s.logger,
+		PanicHandler:           s.panicHandler,
+		DisableFieldSelections: s.disableFieldSelections,
 	}
 	varTypes := make(map[string]*introspection.Type)
 	for _, v := range op.Vars {
diff -pruN 1.6.0-1/graphql_test.go 1.7.0-1/graphql_test.go
--- 1.6.0-1/graphql_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/graphql_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -2915,7 +2915,8 @@ func TestTime(t *testing.T) {
 
 type resolverWithUnexportedMethod struct{}
 
-func (r *resolverWithUnexportedMethod) changeTheNumber(args struct{ NewNumber int32 }) int32 { //lint:ignore U1000 ingore this for now
+//nolint:unused // Method is intentionally left unused to test unexported methods.
+func (r *resolverWithUnexportedMethod) changeTheNumber(args struct{ NewNumber int32 }) int32 {
 	return args.NewNumber
 }
 
@@ -3475,12 +3476,15 @@ type childResolver struct{}
 func (r *childResolver) TriggerError() (string, error) {
 	return "This will never be returned to the client", errExample
 }
+
 func (r *childResolver) NoError() string {
 	return "no error"
 }
+
 func (r *childResolver) Child() *childResolver {
 	return &childResolver{}
 }
+
 func (r *childResolver) NilChild() *childResolver {
 	return nil
 }
@@ -4110,12 +4114,12 @@ type nullableResult struct {
 	Float  string
 }
 
-type nullableResolver struct {
-}
+type nullableResolver struct{}
 
 func (r *nullableResolver) TestNullables(args struct {
 	Input *nullableInput
-}) nullableResult {
+},
+) nullableResult {
 	var res nullableResult
 	if args.Input.String.Set {
 		if args.Input.String.Value == nil {
@@ -4426,11 +4430,14 @@ func stringsEqual(want, have string) str
 	return ""
 }
 
-type queryVarResolver struct{}
-type filterArgs struct {
-	Required string
-	Optional *string
-}
+type (
+	queryVarResolver struct{}
+	filterArgs       struct {
+		Required string
+		Optional *string
+	}
+)
+
 type filterSearchResults struct {
 	Match *string
 }
@@ -4494,12 +4501,14 @@ func TestQueryVariablesValidation(t *tes
 	}})
 }
 
-type interfaceImplementingInterfaceResolver struct{}
-type interfaceImplementingInterfaceExample struct {
-	A string
-	B string
-	C bool
-}
+type (
+	interfaceImplementingInterfaceResolver struct{}
+	interfaceImplementingInterfaceExample  struct {
+		A string
+		B string
+		C bool
+	}
+)
 
 func (r *interfaceImplementingInterfaceResolver) Hey() *interfaceImplementingInterfaceExample {
 	return &interfaceImplementingInterfaceExample{
@@ -4605,13 +4614,15 @@ func TestMaxQueryLength(t *testing.T) {
 	})
 }
 
-type RootResolver struct{}
-type QueryResolver struct{}
-type MutationResolver struct{}
-type SubscriptionResolver struct {
-	err      error
-	upstream <-chan *helloEventResolver
-}
+type (
+	RootResolver         struct{}
+	QueryResolver        struct{}
+	MutationResolver     struct{}
+	SubscriptionResolver struct {
+		err      error
+		upstream <-chan *helloEventResolver
+	}
+)
 
 func (r *RootResolver) Query() *QueryResolver {
 	return &QueryResolver{}
diff -pruN 1.6.0-1/internal/exec/exec.go 1.7.0-1/internal/exec/exec.go
--- 1.6.0-1/internal/exec/exec.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/exec/exec.go	2025-08-19 13:15:23.000000000 +0000
@@ -14,6 +14,7 @@ import (
 	"github.com/graph-gophers/graphql-go/internal/exec/resolvable"
 	"github.com/graph-gophers/graphql-go/internal/exec/selected"
 	"github.com/graph-gophers/graphql-go/internal/query"
+	"github.com/graph-gophers/graphql-go/internal/selections"
 	"github.com/graph-gophers/graphql-go/log"
 	"github.com/graph-gophers/graphql-go/trace/tracer"
 )
@@ -25,6 +26,7 @@ type Request struct {
 	Logger                   log.Logger
 	PanicHandler             errors.PanicHandler
 	SubscribeResolverTimeout time.Duration
+	DisableFieldSelections   bool
 }
 
 func (r *Request) handlePanic(ctx context.Context) {
@@ -226,6 +228,9 @@ func execFieldSelection(ctx context.Cont
 			return errors.Errorf("%s", err) // don't execute any more resolvers if context got cancelled
 		}
 
+		if len(f.sels) > 0 && !r.DisableFieldSelections {
+			ctx = selections.With(ctx, f.sels)
+		}
 		res, resolverErr := f.resolve(ctx)
 		if resolverErr != nil {
 			err := errors.Errorf("%s", resolverErr)
diff -pruN 1.6.0-1/internal/exec/packer/packer.go 1.7.0-1/internal/exec/packer/packer.go
--- 1.6.0-1/internal/exec/packer/packer.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/exec/packer/packer.go	2025-08-19 13:15:23.000000000 +0000
@@ -383,7 +383,7 @@ func unwrapNonNull(t ast.Type) (ast.Type
 }
 
 func stripUnderscore(s string) string {
-	return strings.Replace(s, "_", "", -1)
+	return strings.ReplaceAll(s, "_", "")
 }
 
 // NullUnmarshaller is an unmarshaller that can handle a nil input
diff -pruN 1.6.0-1/internal/exec/resolvable/resolvable.go 1.7.0-1/internal/exec/resolvable/resolvable.go
--- 1.6.0-1/internal/exec/resolvable/resolvable.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/exec/resolvable/resolvable.go	2025-08-19 13:15:23.000000000 +0000
@@ -312,8 +312,7 @@ func makeScalarExec(t *ast.ScalarTypeDef
 	return &Scalar{}, nil
 }
 
-func (b *execBuilder) makeObjectExec(typeName string, fields ast.FieldsDefinition, possibleTypes []*ast.ObjectTypeDefinition,
-	interfaces []*ast.InterfaceTypeDefinition, nonNull bool, resolverType reflect.Type) (*Object, error) {
+func (b *execBuilder) makeObjectExec(typeName string, fields ast.FieldsDefinition, possibleTypes []*ast.ObjectTypeDefinition, interfaces []*ast.InterfaceTypeDefinition, nonNull bool, resolverType reflect.Type) (*Object, error) {
 	if !nonNull {
 		if resolverType.Kind() != reflect.Ptr && resolverType.Kind() != reflect.Interface {
 			return nil, fmt.Errorf("%s is not a pointer or interface", resolverType)
@@ -340,7 +339,7 @@ func (b *execBuilder) makeObjectExec(typ
 		}
 		if methodIndex == -1 && len(fieldIndex) == 0 {
 			var hint string
-			if findMethod(reflect.PtrTo(resolverType), f.Name) != -1 {
+			if findMethod(reflect.PointerTo(resolverType), f.Name) != -1 {
 				hint = " (hint: the method exists on the pointer type)"
 			}
 			return nil, fmt.Errorf("%s does not resolve %q: missing method for field %q%s", resolverType, typeName, f.Name, hint)
@@ -410,8 +409,10 @@ func (b *execBuilder) makeObjectExec(typ
 	}, nil
 }
 
-var contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
-var errorType = reflect.TypeOf((*error)(nil)).Elem()
+var (
+	contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
+	errorType   = reflect.TypeOf((*error)(nil)).Elem()
+)
 
 func (b *execBuilder) makeFieldExec(typeName string, f *ast.FieldDefinition, m reflect.Method, sf reflect.StructField, methodIndex int, fieldIndex []int, methodHasReceiver bool) (*Field, error) {
 	var argsPacker *packer.StructPacker
@@ -588,7 +589,7 @@ func unwrapNonNull(t ast.Type) (ast.Type
 }
 
 func stripUnderscore(s string) string {
-	return strings.Replace(s, "_", "", -1)
+	return strings.ReplaceAll(s, "_", "")
 }
 
 func unwrapPtr(t reflect.Type) reflect.Type {
diff -pruN 1.6.0-1/internal/exec/selected/selected.go 1.7.0-1/internal/exec/selected/selected.go
--- 1.6.0-1/internal/exec/selected/selected.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/exec/selected/selected.go	2025-08-19 13:15:23.000000000 +0000
@@ -101,7 +101,7 @@ func applySelectionSet(r *Request, s *re
 			case "__schema":
 				if r.AllowIntrospection {
 					flattenedSels = append(flattenedSels, &SchemaField{
-						Field:       s.Meta.FieldSchema,
+						Field:       s.FieldSchema,
 						Alias:       field.Alias.Name,
 						Sels:        applySelectionSet(r, s, s.Meta.Schema, field.SelectionSet),
 						Async:       true,
@@ -125,9 +125,9 @@ func applySelectionSet(r *Request, s *re
 					}
 
 					flattenedSels = append(flattenedSels, &SchemaField{
-						Field:       s.Meta.FieldType,
+						Field:       s.FieldType,
 						Alias:       field.Alias.Name,
-						Sels:        applySelectionSet(r, s, s.Meta.Type, field.SelectionSet),
+						Sels:        applySelectionSet(r, s, s.Type, field.SelectionSet),
 						Async:       true,
 						FixedResult: reflect.ValueOf(resolvedType),
 					})
diff -pruN 1.6.0-1/internal/exec/subscribe.go 1.7.0-1/internal/exec/subscribe.go
--- 1.6.0-1/internal/exec/subscribe.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/exec/subscribe.go	2025-08-19 13:15:23.000000000 +0000
@@ -61,8 +61,8 @@ func (r *Request) Subscribe(ctx context.
 	}()
 
 	// Handles the case where the locally executed func above panicked
-	if len(r.Request.Errs) > 0 {
-		return sendAndReturnClosed(&Response{Errors: r.Request.Errs})
+	if len(r.Errs) > 0 {
+		return sendAndReturnClosed(&Response{Errors: r.Errs})
 	}
 
 	if f == nil {
@@ -115,9 +115,9 @@ func (r *Request) Subscribe(ctx context.
 
 				subR := &Request{
 					Request: selected.Request{
-						Doc:    r.Request.Doc,
-						Vars:   r.Request.Vars,
-						Schema: r.Request.Schema,
+						Doc:    r.Doc,
+						Vars:   r.Vars,
+						Schema: r.Schema,
 					},
 					Limiter: r.Limiter,
 					Tracer:  r.Tracer,
diff -pruN 1.6.0-1/internal/schema/schema.go 1.7.0-1/internal/schema/schema.go
--- 1.6.0-1/internal/schema/schema.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/schema/schema.go	2025-08-19 13:15:23.000000000 +0000
@@ -364,9 +364,9 @@ func parseSchema(s *ast.Schema, l *commo
 		switch x := l.ConsumeIdent(); x {
 
 		case "schema":
-			s.SchemaDefinition.Present = true
-			s.SchemaDefinition.Loc = l.Location()
-			s.SchemaDefinition.Desc = desc
+			s.Present = true
+			s.Loc = l.Location()
+			s.Desc = desc
 			s.SchemaDefinition.Directives = common.ParseDirectives(l)
 			l.ConsumeToken('{')
 			for l.Peek() != '}' {
@@ -429,11 +429,7 @@ func parseSchema(s *ast.Schema, l *commo
 func parseObjectDef(l *common.Lexer) *ast.ObjectTypeDefinition {
 	object := &ast.ObjectTypeDefinition{Loc: l.Location(), Name: l.ConsumeIdent()}
 
-	for {
-		if l.Peek() == '{' {
-			break
-		}
-
+	for l.Peek() != '{' {
 		if l.Peek() == '@' {
 			object.Directives = common.ParseDirectives(l)
 			continue
@@ -458,7 +454,6 @@ func parseObjectDef(l *common.Lexer) *as
 	l.ConsumeToken('}')
 
 	return object
-
 }
 
 func parseInterfaceDef(l *common.Lexer) *ast.InterfaceTypeDefinition {
@@ -531,6 +526,7 @@ func parseEnumDef(l *common.Lexer) *ast.
 	l.ConsumeToken('}')
 	return enum
 }
+
 func parseDirectiveDef(l *common.Lexer) *ast.DirectiveDefinition {
 	l.ConsumeToken('@')
 	loc := l.Location()
@@ -573,7 +569,7 @@ func parseExtension(s *ast.Schema, l *co
 	loc := l.Location()
 	switch x := l.ConsumeIdent(); x {
 	case "schema":
-		s.SchemaDefinition.Present = true
+		s.Present = true
 		s.SchemaDefinition.Directives = append(s.SchemaDefinition.Directives, common.ParseDirectives(l)...)
 		if l.Peek() == '{' { // in schema extensions the body is optional
 			l.ConsumeToken('{')
diff -pruN 1.6.0-1/internal/schema/schema_internal_test.go 1.7.0-1/internal/schema/schema_internal_test.go
--- 1.6.0-1/internal/schema/schema_internal_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/schema/schema_internal_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -175,7 +175,6 @@ func TestParseSchemaDef(t *testing.T) {
 				s := New()
 				parseSchema(s, lex)
 				actual = &s.SchemaDefinition
-
 			}
 			err := lex.CatchSyntaxError(parse)
 
@@ -199,7 +198,8 @@ func TestParseInterfaceDef(t *testing.T)
 		expected: &ast.InterfaceTypeDefinition{
 			Name:   "Greeting",
 			Loc:    errors.Location{Line: 1, Column: 1},
-			Fields: ast.FieldsDefinition{&ast.FieldDefinition{Name: "field"}}},
+			Fields: ast.FieldsDefinition{&ast.FieldDefinition{Name: "field"}},
+		},
 	}}
 
 	for _, test := range tests {
diff -pruN 1.6.0-1/internal/selections/context.go 1.7.0-1/internal/selections/context.go
--- 1.6.0-1/internal/selections/context.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/internal/selections/context.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,107 @@
+// Package selections is for internal use to share selection context between
+// the execution engine and the public graphql package without creating an
+// import cycle.
+//
+// The execution layer stores the flattened child selection set for the field
+// currently being resolved. The public API converts this into user-friendly
+// helpers (SelectedFieldNames, etc.).
+package selections
+
+import (
+	"context"
+	"sync"
+
+	"github.com/graph-gophers/graphql-go/internal/exec/selected"
+)
+
+// ctxKey is an unexported unique type used as context key.
+type ctxKey struct{}
+
+// Lazy holds raw selections and computes the flattened, deduped name list once on demand.
+type Lazy struct {
+	raw   []selected.Selection
+	once  sync.Once
+	names []string
+	set   map[string]struct{}
+}
+
+// Names returns the deduplicated child field names computing them once.
+func (l *Lazy) Names() []string {
+	if l == nil {
+		return nil
+	}
+	l.once.Do(func() {
+		seen := make(map[string]struct{}, len(l.raw))
+		ordered := make([]string, 0, len(l.raw))
+		for _, s := range l.raw {
+			switch s := s.(type) {
+			case *selected.SchemaField:
+				name := s.Name
+				if len(name) >= 2 && name[:2] == "__" {
+					continue
+				}
+				if _, ok := seen[name]; !ok {
+					seen[name] = struct{}{}
+					ordered = append(ordered, name)
+				}
+			case *selected.TypeAssertion:
+				collectFromTypeAssertion(&ordered, seen, s.Sels)
+			case *selected.TypenameField:
+				continue
+			}
+		}
+		l.names = ordered
+		l.set = seen
+	})
+	// Return a copy to keep internal slice immutable to callers.
+	out := make([]string, len(l.names))
+	copy(out, l.names)
+	return out
+}
+
+// Has reports if a field name is in the selection list.
+func (l *Lazy) Has(name string) bool {
+	if l == nil {
+		return false
+	}
+	if l.set == nil { // ensure computed
+		_ = l.Names()
+	}
+	_, ok := l.set[name]
+	return ok
+}
+
+// collectFromTypeAssertion flattens selections under a type assertion fragment.
+func collectFromTypeAssertion(dst *[]string, seen map[string]struct{}, sels []selected.Selection) {
+	for _, s := range sels {
+		switch s := s.(type) {
+		case *selected.SchemaField:
+			name := s.Name
+			if len(name) >= 2 && name[:2] == "__" {
+				continue
+			}
+			if _, ok := seen[name]; !ok {
+				seen[name] = struct{}{}
+				*dst = append(*dst, name)
+			}
+		case *selected.TypeAssertion:
+			collectFromTypeAssertion(dst, seen, s.Sels)
+		case *selected.TypenameField:
+			continue
+		}
+	}
+}
+
+// With stores a lazy wrapper for selections in the context.
+func With(ctx context.Context, sels []selected.Selection) context.Context {
+	if len(sels) == 0 {
+		return ctx
+	}
+	return context.WithValue(ctx, ctxKey{}, &Lazy{raw: sels})
+}
+
+// FromContext retrieves the lazy wrapper (may be nil).
+func FromContext(ctx context.Context) *Lazy {
+	v, _ := ctx.Value(ctxKey{}).(*Lazy)
+	return v
+}
diff -pruN 1.6.0-1/internal/validation/validation.go 1.7.0-1/internal/validation/validation.go
--- 1.6.0-1/internal/validation/validation.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/validation/validation.go	2025-08-19 13:15:23.000000000 +0000
@@ -934,7 +934,7 @@ func validateBasicLit(v *ast.PrimitiveVa
 		case "ID":
 			return (v.Type == scanner.Int && validateBuiltInScalar(v.Text, "Int")) || (v.Type == scanner.String && validateBuiltInScalar(v.Text, "String"))
 		default:
-			//TODO: Type-check against expected type by Unmarshalling
+			// TODO: Type-check against expected type by Unmarshalling
 			return true
 		}
 
diff -pruN 1.6.0-1/internal/validation/validation_test.go 1.7.0-1/internal/validation/validation_test.go
--- 1.6.0-1/internal/validation/validation_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/internal/validation/validation_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -1,13 +1,12 @@
 package validation_test
 
 import (
+	"encoding/json"
 	"os"
 	"reflect"
 	"sort"
 	"testing"
 
-	"encoding/json"
-
 	"github.com/graph-gophers/graphql-go/ast"
 	"github.com/graph-gophers/graphql-go/errors"
 	"github.com/graph-gophers/graphql-go/internal/query"
diff -pruN 1.6.0-1/log/log.go 1.7.0-1/log/log.go
--- 1.6.0-1/log/log.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/log/log.go	2025-08-19 13:15:23.000000000 +0000
@@ -6,15 +6,23 @@ import (
 	"runtime"
 )
 
-// Logger is the interface used to log panics that occur during query execution. It is settable via graphql.ParseSchema
+// Logger is the interface used to log panics that occur during query execution. It is settable via graphql.ParseSchema.
 type Logger interface {
 	LogPanic(ctx context.Context, value interface{})
 }
 
-// DefaultLogger is the default logger used to log panics that occur during query execution
+// LoggerFunc is a function type that implements the Logger interface.
+type LoggerFunc func(ctx context.Context, value interface{})
+
+// LogPanic calls the LoggerFunc with the given context and panic value.
+func (f LoggerFunc) LogPanic(ctx context.Context, value interface{}) {
+	f(ctx, value)
+}
+
+// DefaultLogger is the default logger used to log panics that occur during query execution.
 type DefaultLogger struct{}
 
-// LogPanic is used to log recovered panic values that occur during query execution
+// LogPanic is used to log recovered panic values that occur during query execution.
 func (l *DefaultLogger) LogPanic(ctx context.Context, value interface{}) {
 	const size = 64 << 10
 	buf := make([]byte, size)
diff -pruN 1.6.0-1/log/log_test.go 1.7.0-1/log/log_test.go
--- 1.6.0-1/log/log_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/log/log_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,42 @@
+package log_test
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/graph-gophers/graphql-go"
+	"github.com/graph-gophers/graphql-go/log"
+)
+
+func ExampleLoggerFunc() {
+	logfn := log.LoggerFunc(func(ctx context.Context, err interface{}) {
+		// Here you can handle the panic, e.g., log it or send it to an error tracking service.
+		fmt.Printf("graphql: panic occurred: %v", err)
+	})
+
+	opts := []graphql.SchemaOpt{
+		graphql.Logger(logfn),
+		graphql.UseFieldResolvers(),
+	}
+
+	schemadef := `
+		type Query {
+			hello: String!
+		}
+	`
+	resolver := &struct {
+		Hello func() string
+	}{
+		Hello: func() string {
+			// Simulate a panic
+			panic("something went wrong")
+		},
+	}
+
+	schema := graphql.MustParseSchema(schemadef, resolver, opts...)
+	// Now, when you execute a query that causes a panic, it will be logged using the provided LoggerFunc.
+	schema.Exec(context.Background(), "{ hello }", "", nil)
+
+	// Output:
+	// graphql: panic occurred: something went wrong
+}
diff -pruN 1.6.0-1/selection.go 1.7.0-1/selection.go
--- 1.6.0-1/selection.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/selection.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,59 @@
+package graphql
+
+import (
+	"context"
+	"sort"
+
+	"github.com/graph-gophers/graphql-go/internal/selections"
+)
+
+// SelectedFieldNames returns the set of immediate child field names selected
+// on the value returned by the current resolver. It returns an empty slice
+// when the current field's return type is a leaf (scalar / enum) or when the
+// feature was disabled at schema construction via DisableFieldSelections.
+// The returned slice is a copy and is safe for the caller to modify.
+//
+// It is intentionally simple and does not expose the internal AST. If more
+// detailed information is needed in the future (e.g. arguments per child,
+// nested trees) a separate API can be added without breaking this one.
+//
+// Notes:
+//   - Fragment spreads & inline fragments are flattened; the union of all
+//     possible child fields is returned (deduplicated, preserving first
+//     appearance order in the query document).
+//   - Field aliases are ignored; the original schema field names are returned.
+//   - Meta fields beginning with "__" (including __typename) are excluded.
+func SelectedFieldNames(ctx context.Context) []string {
+	// If no selection info is present (leaf field or no child selections), return empty slice.
+	lazy := selections.FromContext(ctx)
+	if lazy == nil {
+		return []string{}
+	}
+	return lazy.Names()
+}
+
+// HasSelectedField returns true if the immediate child selection list contains
+// the provided field name (case sensitive). It returns false for leaf return
+// types and when DisableFieldSelections was used.
+func HasSelectedField(ctx context.Context, name string) bool {
+	lazy := selections.FromContext(ctx)
+	if lazy == nil {
+		return false
+	}
+	return lazy.Has(name)
+}
+
+// SortedSelectedFieldNames returns the same data as SelectedFieldNames but
+// sorted lexicographically for deterministic ordering scenarios (e.g. cache
+// key generation). It will also return an empty slice when selections are
+// disabled.
+func SortedSelectedFieldNames(ctx context.Context) []string {
+	names := SelectedFieldNames(ctx)
+	if len(names) <= 1 {
+		return names
+	}
+	out := make([]string, len(names))
+	copy(out, names)
+	sort.Strings(out)
+	return out
+}
diff -pruN 1.6.0-1/selection_bench_test.go 1.7.0-1/selection_bench_test.go
--- 1.6.0-1/selection_bench_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/selection_bench_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,117 @@
+package graphql_test
+
+import (
+	"context"
+	"fmt"
+	"testing"
+
+	graphql "github.com/graph-gophers/graphql-go"
+)
+
+// This benchmark compares query execution when resolvers do NOT call the
+// selection helpers vs when they call SelectedFieldNames at object boundaries.
+// It documents the lazy overhead of computing child field selections.
+
+const lazyBenchSchema = `
+			schema { query: Query }
+			type Query { hero: Human }
+			type Human { id: ID! name: String friends: [Human!]! }
+		`
+
+// Simple in-memory data graph.
+type human struct {
+	id, name string
+	friends  []*human
+}
+
+// Build a small graph once outside the benchmark loops.
+var benchHero *human
+
+func init() {
+	// Create 5 friends (no recursive friends to keep size stable).
+	friends := make([]*human, 5)
+	for i := range friends {
+		friends[i] = &human{id: fmt.Sprintf("F%d", i), name: "Friend"}
+	}
+	benchHero = &human{id: "H1", name: "Hero", friends: friends}
+}
+
+// Baseline resolvers (do NOT invoke selection helpers).
+type (
+	rootBaseline          struct{}
+	humanResolverBaseline struct{ h *human }
+)
+
+func (r *rootBaseline) Hero(ctx context.Context) *humanResolverBaseline {
+	return &humanResolverBaseline{h: benchHero}
+}
+func (h *humanResolverBaseline) ID() graphql.ID { return graphql.ID(h.h.id) }
+func (h *humanResolverBaseline) Name() *string  { return &h.h.name }
+func (h *humanResolverBaseline) Friends(ctx context.Context) []*humanResolverBaseline {
+	out := make([]*humanResolverBaseline, len(h.h.friends))
+	for i, f := range h.h.friends {
+		out[i] = &humanResolverBaseline{h: f}
+	}
+	return out
+}
+
+// Instrumented resolvers (CALL selection helpers once per object-level resolver).
+type (
+	rootWithSel          struct{}
+	humanResolverWithSel struct{ h *human }
+)
+
+func (r *rootWithSel) Hero(ctx context.Context) *humanResolverWithSel {
+	// Selection list for hero object (id, name, friends)
+	_ = graphql.SelectedFieldNames(ctx)
+	return &humanResolverWithSel{h: benchHero}
+}
+
+func (h *humanResolverWithSel) ID(ctx context.Context) graphql.ID { // leaf: expecting empty slice
+	return graphql.ID(h.h.id)
+}
+
+func (h *humanResolverWithSel) Name(ctx context.Context) *string { // leaf
+	return &h.h.name
+}
+
+func (h *humanResolverWithSel) Friends(ctx context.Context) []*humanResolverWithSel {
+	// Selection list on list field: children of Human inside list items.
+	_ = graphql.SelectedFieldNames(ctx)
+	out := make([]*humanResolverWithSel, len(h.h.friends))
+	for i, f := range h.h.friends {
+		// For each friend object we also call once at the object resolver boundary.
+		out[i] = &humanResolverWithSel{h: f}
+	}
+	return out
+}
+
+// Query used for both benchmarks.
+const lazyBenchQuery = `query { hero { id name friends { id name } } }`
+
+func BenchmarkFieldSelections_NoUsage(b *testing.B) {
+	schema := graphql.MustParseSchema(lazyBenchSchema, &rootBaseline{})
+	ctx := context.Background()
+	b.ReportAllocs()
+	for b.Loop() {
+		_ = schema.Exec(ctx, lazyBenchQuery, "", nil)
+	}
+}
+
+func BenchmarkFieldSelections_Disabled_NoUsage(b *testing.B) {
+	schema := graphql.MustParseSchema(lazyBenchSchema, &rootBaseline{}, graphql.DisableFieldSelections())
+	ctx := context.Background()
+	b.ReportAllocs()
+	for b.Loop() {
+		_ = schema.Exec(ctx, lazyBenchQuery, "", nil)
+	}
+}
+
+func BenchmarkFieldSelections_WithSelectedFieldNames(b *testing.B) {
+	schema := graphql.MustParseSchema(lazyBenchSchema, &rootWithSel{})
+	ctx := context.Background()
+	b.ReportAllocs()
+	for b.Loop() {
+		_ = schema.Exec(ctx, lazyBenchQuery, "", nil)
+	}
+}
diff -pruN 1.6.0-1/selection_test.go 1.7.0-1/selection_test.go
--- 1.6.0-1/selection_test.go	1970-01-01 00:00:00.000000000 +0000
+++ 1.7.0-1/selection_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -0,0 +1,164 @@
+package graphql_test
+
+import (
+	"context"
+	"testing"
+
+	"github.com/graph-gophers/graphql-go"
+)
+
+const selectionTestSchema = `
+    schema { query: Query }
+    type Query { hero: Human }
+    type Human { id: ID! name: String }
+`
+
+type selectionRoot struct {
+	t            *testing.T
+	expectNames  []string
+	expectSorted []string
+	hasChecks    map[string]bool
+}
+
+type selectionHuman struct {
+	t    *testing.T
+	id   string
+	name string
+}
+
+func (r *selectionRoot) Hero(ctx context.Context) *selectionHuman {
+	names := graphql.SelectedFieldNames(ctx)
+	sorted := graphql.SortedSelectedFieldNames(ctx)
+	if !equalStringSlices(names, r.expectNames) {
+		r.t.Errorf("SelectedFieldNames = %v, want %v", names, r.expectNames)
+	}
+	if !equalStringSlices(sorted, r.expectSorted) {
+		r.t.Errorf("SortedSelectedFieldNames = %v, want %v", sorted, r.expectSorted)
+	}
+	for name, want := range r.hasChecks {
+		if got := graphql.HasSelectedField(ctx, name); got != want {
+			r.t.Errorf("HasSelectedField(%q) = %v, want %v", name, got, want)
+		}
+	}
+	return &selectionHuman{t: r.t, id: "h1", name: "Luke"}
+}
+
+// Object-level assertions happen in Hero via a wrapper test function; leaf behavior tested here.
+func (h *selectionHuman) ID() graphql.ID { return graphql.ID(h.id) }
+
+func (h *selectionHuman) Name(ctx context.Context) *string {
+	// Leaf field: should always produce empty selections regardless of enable/disable.
+	if got := graphql.SelectedFieldNames(ctx); len(got) != 0 {
+		h.t.Errorf("leaf field SelectedFieldNames = %v, want empty", got)
+	}
+	if graphql.HasSelectedField(ctx, "anything") {
+		h.t.Errorf("leaf field HasSelectedField unexpectedly true")
+	}
+	if sorted := graphql.SortedSelectedFieldNames(ctx); len(sorted) != 0 {
+		h.t.Errorf("leaf field SortedSelectedFieldNames = %v, want empty", sorted)
+	}
+	return &h.name
+}
+
+func TestFieldSelectionHelpers(t *testing.T) {
+	tests := []struct {
+		name         string
+		schemaOpts   []graphql.SchemaOpt
+		query        string
+		expectNames  []string // expected order from SelectedFieldNames at object boundary
+		expectSorted []string // expected from SortedSelectedFieldNames at object boundary
+		hasChecks    map[string]bool
+	}{
+		{
+			name:         "enabled object order preserved and sorted copy",
+			query:        `query { hero { name id } }`, // order intentionally name,id
+			expectNames:  []string{"name", "id"},
+			expectSorted: []string{"id", "name"},
+			hasChecks:    map[string]bool{"id": true, "name": true, "missing": false},
+		},
+		{
+			name:         "enabled only one field selected",
+			query:        `query { hero { id } }`, // order intentionally name,id
+			expectNames:  []string{"id"},
+			expectSorted: []string{"id"},
+			hasChecks:    map[string]bool{"id": true, "name": false, "missing": false},
+		},
+		{
+			name:         "disabled object returns empty",
+			schemaOpts:   []graphql.SchemaOpt{graphql.DisableFieldSelections()},
+			query:        `query { hero { name id } }`,
+			expectNames:  []string{},
+			expectSorted: []string{},
+			hasChecks:    map[string]bool{"id": false, "name": false},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			root := &selectionRoot{t: t, expectNames: tt.expectNames, expectSorted: tt.expectSorted, hasChecks: tt.hasChecks}
+			s := graphql.MustParseSchema(selectionTestSchema, root, tt.schemaOpts...)
+			resp := s.Exec(context.Background(), tt.query, "", nil)
+			if len(resp.Errors) > 0 {
+				t.Fatalf("execution errors: %v", resp.Errors)
+			}
+		})
+	}
+}
+
+func TestSelectedFieldNames_FragmentsAliasesMeta(t *testing.T) {
+	tests := []struct {
+		name        string
+		query       string
+		expectNames []string
+		hasChecks   map[string]bool
+	}{
+		{
+			name:        "alias ignored order preserved",
+			query:       `query { hero { idAlias: id name } }`,
+			expectNames: []string{"id", "name"},
+			hasChecks:   map[string]bool{"id": true, "idAlias": false, "name": true},
+		},
+		{
+			name:        "fragment spread flattened",
+			query:       `fragment HFields on Human { id name } query { hero { ...HFields } }`,
+			expectNames: []string{"id", "name"},
+			hasChecks:   map[string]bool{"id": true, "name": true},
+		},
+		{
+			name:        "inline fragment dedup",
+			query:       `query { hero { id ... on Human { id name } } }`,
+			expectNames: []string{"id", "name"},
+			hasChecks:   map[string]bool{"id": true, "name": true},
+		},
+		{
+			name:        "meta field excluded",
+			query:       `query { hero { id __typename name } }`,
+			expectNames: []string{"id", "name"},
+			hasChecks:   map[string]bool{"id": true, "name": true, "__typename": false},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			root := &selectionRoot{t: t, expectNames: tt.expectNames, expectSorted: tt.expectNames, hasChecks: tt.hasChecks}
+			s := graphql.MustParseSchema(selectionTestSchema, root)
+			resp := s.Exec(context.Background(), tt.query, "", nil)
+			if len(resp.Errors) > 0 {
+				t.Fatalf("execution errors: %v", resp.Errors)
+			}
+		})
+	}
+}
+
+// equalStringSlices compares content and order.
+func equalStringSlices(a, b []string) bool {
+	if len(a) != len(b) {
+		return false
+	}
+	for i := range a {
+		if a[i] != b[i] {
+			return false
+		}
+	}
+	return true
+}
diff -pruN 1.6.0-1/subscription_test.go 1.7.0-1/subscription_test.go
--- 1.6.0-1/subscription_test.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/subscription_test.go	2025-08-19 13:15:23.000000000 +0000
@@ -24,8 +24,10 @@ func (r *helloResolver) Hello() string {
 	return "Hello world!"
 }
 
-var errResolver = errors.New("resolver error")
-var resolverQueryErr = &qerrors.QueryError{Message: "query", ResolverError: errResolver}
+var (
+	errResolver      = errors.New("resolver error")
+	resolverQueryErr = &qerrors.QueryError{Message: "query", ResolverError: errResolver}
+)
 
 type helloSaidResolver struct {
 	err      error
diff -pruN 1.6.0-1/trace/tracer/tracer.go 1.7.0-1/trace/tracer/tracer.go
--- 1.6.0-1/trace/tracer/tracer.go	2025-02-22 11:42:48.000000000 +0000
+++ 1.7.0-1/trace/tracer/tracer.go	2025-08-19 13:15:23.000000000 +0000
@@ -8,9 +8,11 @@ import (
 	"github.com/graph-gophers/graphql-go/introspection"
 )
 
-type QueryFinishFunc = func([]*errors.QueryError)
-type FieldFinishFunc = func(*errors.QueryError)
-type ValidationFinishFunc = func([]*errors.QueryError)
+type (
+	QueryFinishFunc      = func([]*errors.QueryError)
+	FieldFinishFunc      = func(*errors.QueryError)
+	ValidationFinishFunc = func([]*errors.QueryError)
+)
 
 type Tracer interface {
 	TraceQuery(ctx context.Context, queryString string, operationName string, variables map[string]interface{}, varTypes map[string]*introspection.Type) (context.Context, QueryFinishFunc)
