Skip to content

Replace direct ryu usage with zmij for float formatting#865

Draft
Copilot wants to merge 76 commits into
mainfrom
copilot/replace-ryu-with-zmij
Draft

Replace direct ryu usage with zmij for float formatting#865
Copilot wants to merge 76 commits into
mainfrom
copilot/replace-ryu-with-zmij

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 18, 2026

  • Check branch status and current commit state
  • Rebase branch onto latest main
  • Run targeted validation for affected crates
  • Reply to PR comment with resulting commit hash

💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Copilot AI changed the title [WIP] Replace ryu crate with zmij Replace direct ryu usage with zmij for float formatting Mar 18, 2026
Copilot AI requested a review from kamilkisiela March 18, 2026 15:03
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 18, 2026

🐋 This PR was built and pushed to the following Docker images:

Image Names: ghcr.io/graphql-hive/router

Platforms: linux/amd64,linux/arm64

Image Tags: ghcr.io/graphql-hive/router:pr-865 ghcr.io/graphql-hive/router:sha-20e5cb2

Docker metadata
{
"buildx.build.provenance/linux/amd64": {
  "builder": {
    "id": "https://github.com/graphql-hive/router/actions/runs/23482584243/attempts/1"
  },
  "buildType": "https://mobyproject.org/buildkit@v1",
  "materials": [
    {
      "uri": "pkg:docker/docker/dockerfile@1.22",
      "digest": {
        "sha256": "4a43a54dd1fedceb30ba47e76cfcf2b47304f4161c0caeac2db1c61804ea3c91"
      }
    },
    {
      "uri": "pkg:docker/gcr.io/distroless/cc-debian12@latest?platform=linux%2Famd64",
      "digest": {
        "sha256": "329e54034ce498f9c6b345044e8f530c6691f99e94a92446f68c0adf9baa8464"
      }
    }
  ],
  "invocation": {
    "configSource": {
      "entryPoint": "router.Dockerfile"
    },
    "parameters": {
      "frontend": "gateway.v0",
      "args": {
        "cmdline": "docker/dockerfile:1.22",
        "label:org.opencontainers.image.created": "2026-03-24T09:47:12.991Z",
        "label:org.opencontainers.image.description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
        "label:org.opencontainers.image.licenses": "MIT",
        "label:org.opencontainers.image.revision": "20e5cb2f06fd49b83463db35b8ba8fbe263fb399",
        "label:org.opencontainers.image.source": "https://github.com/graphql-hive/router",
        "label:org.opencontainers.image.title": "router",
        "label:org.opencontainers.image.url": "https://github.com/graphql-hive/router",
        "label:org.opencontainers.image.vendor": "theguild",
        "label:org.opencontainers.image.version": "pr-865",
        "source": "docker/dockerfile:1.22"
      },
      "locals": [
        {
          "name": "context"
        },
        {
          "name": "dockerfile"
        }
      ]
    },
    "environment": {
      "github_actor": "kamilkisiela",
      "github_actor_id": "8167190",
      "github_event_name": "pull_request",
      "github_event_payload": {
        "action": "synchronize",
        "after": "e197521774a40772c629fd3d37d40d532be6c965",
        "before": "40fa07a5b841199e4a8e201554fd5e62a10a66fc",
        "enterprise": {
          "avatar_url": "https://avatars.githubusercontent.com/b/187753?v=4",
          "created_at": "2024-07-02T08:52:28Z",
          "description": "",
          "html_url": "https://github.com/enterprises/the-guild",
          "id": 187753,
          "name": "The Guild",
          "node_id": "E_kgDOAALdaQ",
          "slug": "the-guild",
          "updated_at": "2026-03-11T16:47:15Z",
          "website_url": "https://the-guild.dev/"
        },
        "number": 865,
        "organization": {
          "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
          "description": "Schema registry, analytics and gateway for GraphQL federation and other GraphQL APIs.",
          "events_url": "https://api.github.com/orgs/graphql-hive/events",
          "hooks_url": "https://api.github.com/orgs/graphql-hive/hooks",
          "id": 182742256,
          "issues_url": "https://api.github.com/orgs/graphql-hive/issues",
          "login": "graphql-hive",
          "members_url": "https://api.github.com/orgs/graphql-hive/members{/member}",
          "node_id": "O_kgDOCuRs8A",
          "public_members_url": "https://api.github.com/orgs/graphql-hive/public_members{/member}",
          "repos_url": "https://api.github.com/orgs/graphql-hive/repos",
          "url": "https://api.github.com/orgs/graphql-hive"
        },
        "pull_request": {
          "_links": {
            "comments": {
              "href": "https://api.github.com/repos/graphql-hive/router/issues/865/comments"
            },
            "commits": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865/commits"
            },
            "html": {
              "href": "https://github.com/graphql-hive/router/pull/865"
            },
            "issue": {
              "href": "https://api.github.com/repos/graphql-hive/router/issues/865"
            },
            "review_comment": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/comments{/number}"
            },
            "review_comments": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865/comments"
            },
            "self": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865"
            },
            "statuses": {
              "href": "https://api.github.com/repos/graphql-hive/router/statuses/e197521774a40772c629fd3d37d40d532be6c965"
            }
          },
          "active_lock_reason": null,
          "additions": 29,
          "assignee": null,
          "assignees": [
            {
              "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
              "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
              "followers_url": "https://api.github.com/users/kamilkisiela/followers",
              "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
              "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/kamilkisiela",
              "id": 8167190,
              "login": "kamilkisiela",
              "node_id": "MDQ6VXNlcjgxNjcxOTA=",
              "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
              "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
              "repos_url": "https://api.github.com/users/kamilkisiela/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/kamilkisiela",
              "user_view_type": "public"
            },
            {
              "avatar_url": "https://avatars.githubusercontent.com/in/1143301?v=4",
              "events_url": "https://api.github.com/users/Copilot/events{/privacy}",
              "followers_url": "https://api.github.com/users/Copilot/followers",
              "following_url": "https://api.github.com/users/Copilot/following{/other_user}",
              "gists_url": "https://api.github.com/users/Copilot/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/apps/copilot-swe-agent",
              "id": 198982749,
              "login": "Copilot",
              "node_id": "BOT_kgDOC9w8XQ",
              "organizations_url": "https://api.github.com/users/Copilot/orgs",
              "received_events_url": "https://api.github.com/users/Copilot/received_events",
              "repos_url": "https://api.github.com/users/Copilot/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/Copilot/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/Copilot/subscriptions",
              "type": "Bot",
              "url": "https://api.github.com/users/Copilot",
              "user_view_type": "public"
            }
          ],
          "author_association": "NONE",
          "auto_merge": null,
          "base": {
            "label": "graphql-hive:main",
            "ref": "main",
            "repo": {
              "allow_auto_merge": false,
              "allow_forking": true,
              "allow_merge_commit": false,
              "allow_rebase_merge": false,
              "allow_squash_merge": true,
              "allow_update_branch": true,
              "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
              "archived": false,
              "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
              "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
              "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
              "clone_url": "https://github.com/graphql-hive/router.git",
              "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
              "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
              "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
              "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
              "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
              "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
              "created_at": "2024-11-20T16:16:12Z",
              "default_branch": "main",
              "delete_branch_on_merge": true,
              "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
              "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
              "disabled": false,
              "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
              "events_url": "https://api.github.com/repos/graphql-hive/router/events",
              "fork": false,
              "forks": 9,
              "forks_count": 9,
              "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
              "full_name": "graphql-hive/router",
              "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
              "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
              "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
              "git_url": "git://github.com/graphql-hive/router.git",
              "has_discussions": false,
              "has_downloads": true,
              "has_issues": true,
              "has_pages": false,
              "has_projects": false,
              "has_pull_requests": true,
              "has_wiki": false,
              "homepage": "https://the-guild.dev/graphql/hive/docs/router",
              "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
              "html_url": "https://github.com/graphql-hive/router",
              "id": 891604244,
              "is_template": false,
              "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
              "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
              "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
              "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
              "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
              "language": "Rust",
              "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
              "license": {
                "key": "mit",
                "name": "MIT License",
                "node_id": "MDc6TGljZW5zZTEz",
                "spdx_id": "MIT",
                "url": "https://api.github.com/licenses/mit"
              },
              "merge_commit_message": "PR_TITLE",
              "merge_commit_title": "MERGE_MESSAGE",
              "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
              "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
              "mirror_url": null,
              "name": "router",
              "node_id": "R_kgDONSTNFA",
              "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
              "open_issues": 61,
              "open_issues_count": 61,
              "owner": {
                "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
                "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
                "followers_url": "https://api.github.com/users/graphql-hive/followers",
                "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
                "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
                "gravatar_id": "",
                "html_url": "https://github.com/graphql-hive",
                "id": 182742256,
                "login": "graphql-hive",
                "node_id": "O_kgDOCuRs8A",
                "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
                "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
                "repos_url": "https://api.github.com/users/graphql-hive/repos",
                "site_admin": false,
                "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
                "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
                "type": "Organization",
                "url": "https://api.github.com/users/graphql-hive",
                "user_view_type": "public"
              },
              "private": false,
              "pull_request_creation_policy": "all",
              "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
              "pushed_at": "2026-03-24T09:34:00Z",
              "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
              "size": 5903,
              "squash_merge_commit_message": "PR_BODY",
              "squash_merge_commit_title": "PR_TITLE",
              "ssh_url": "git@github.com:graphql-hive/router.git",
              "stargazers_count": 79,
              "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
              "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
              "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
              "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
              "svn_url": "https://github.com/graphql-hive/router",
              "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
              "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
              "topics": [
                "apollo-federation",
                "federation",
                "federation-gateway",
                "graphql",
                "graphql-federation",
                "router"
              ],
              "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
              "updated_at": "2026-03-24T00:29:34Z",
              "url": "https://api.github.com/repos/graphql-hive/router",
              "use_squash_pr_title_as_default": true,
              "visibility": "public",
              "watchers": 79,
              "watchers_count": 79,
              "web_commit_signoff_required": false
            },
            "sha": "2522e961a6dca22ad4417a9deefe306eabb2c614",
            "user": {
              "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
              "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
              "followers_url": "https://api.github.com/users/graphql-hive/followers",
              "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
              "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/graphql-hive",
              "id": 182742256,
              "login": "graphql-hive",
              "node_id": "O_kgDOCuRs8A",
              "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
              "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
              "repos_url": "https://api.github.com/users/graphql-hive/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
              "type": "Organization",
              "url": "https://api.github.com/users/graphql-hive",
              "user_view_type": "public"
            }
          },
          "body": "This change replaces direct `ryu` usage with `zmij` in the router codepaths that serialize floating-point values. The goal is to align float-to-string formatting with `zmij` while preserving existing output behavior.\n\n- **Dependency updates**\n  - Swapped direct crate dependencies:\n    - `lib/graphql-tools/Cargo.toml`: `ryu` → `zmij`\n    - `lib/executor/Cargo.toml`: `ryu` → `zmij`\n  - Updated lockfile edges so affected crates now resolve through `zmij`.\n\n- **Runtime formatting path migration**\n  - Updated GraphQL AST minification float formatting:\n    - `lib/graphql-tools/src/parser/query/minify.rs`\n    - `ryu::Buffer` replaced with `zmij::Buffer`.\n  - Updated JSON float writer in plan executor:\n    - `lib/executor/src/json_writer.rs`\n    - `ryu::Buffer` replaced with `zmij::Buffer`.\n\n- **Documentation/comments consistency**\n  - Updated in-code comments in minifier implementation to reference `zmij` instead of `ryu`.\n\n- **Focused regression coverage**\n  - Added targeted tests in `lib/executor/src/json_writer.rs` for:\n    - finite float serialization\n    - non-finite float (`NaN`) serialization to `null`\n\nExample of the core migration:\n\n```rust\nlet mut buffer = zmij::Buffer::new();\nlet s = buffer.format_finite(value);\nwriter.put(s.as_bytes());\n```\n\n<!-- START COPILOT CODING AGENT TIPS -->\n---\n\n💬 Send tasks to Copilot coding agent from [Slack](https://gh.io/cca-slack-docs) and [Teams](https://gh.io/cca-teams-docs) to turn conversations into code. Copilot posts an update in your thread when it's finished.",
          "changed_files": 5,
          "closed_at": null,
          "comments": 1,
          "comments_url": "https://api.github.com/repos/graphql-hive/router/issues/865/comments",
          "commits": 1,
          "commits_url": "https://api.github.com/repos/graphql-hive/router/pulls/865/commits",
          "created_at": "2026-03-18T14:42:51Z",
          "deletions": 11,
          "diff_url": "https://github.com/graphql-hive/router/pull/865.diff",
          "draft": true,
          "head": {
            "label": "graphql-hive:copilot/replace-ryu-with-zmij",
            "ref": "copilot/replace-ryu-with-zmij",
            "repo": {
              "allow_auto_merge": false,
              "allow_forking": true,
              "allow_merge_commit": false,
              "allow_rebase_merge": false,
              "allow_squash_merge": true,
              "allow_update_branch": true,
              "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
              "archived": false,
              "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
              "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
              "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
              "clone_url": "https://github.com/graphql-hive/router.git",
              "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
              "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
              "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
              "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
              "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
              "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
              "created_at": "2024-11-20T16:16:12Z",
              "default_branch": "main",
              "delete_branch_on_merge": true,
              "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
              "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
              "disabled": false,
              "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
              "events_url": "https://api.github.com/repos/graphql-hive/router/events",
              "fork": false,
              "forks": 9,
              "forks_count": 9,
              "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
              "full_name": "graphql-hive/router",
              "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
              "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
              "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
              "git_url": "git://github.com/graphql-hive/router.git",
              "has_discussions": false,
              "has_downloads": true,
              "has_issues": true,
              "has_pages": false,
              "has_projects": false,
              "has_pull_requests": true,
              "has_wiki": false,
              "homepage": "https://the-guild.dev/graphql/hive/docs/router",
              "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
              "html_url": "https://github.com/graphql-hive/router",
              "id": 891604244,
              "is_template": false,
              "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
              "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
              "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
              "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
              "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
              "language": "Rust",
              "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
              "license": {
                "key": "mit",
                "name": "MIT License",
                "node_id": "MDc6TGljZW5zZTEz",
                "spdx_id": "MIT",
                "url": "https://api.github.com/licenses/mit"
              },
              "merge_commit_message": "PR_TITLE",
              "merge_commit_title": "MERGE_MESSAGE",
              "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
              "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
              "mirror_url": null,
              "name": "router",
              "node_id": "R_kgDONSTNFA",
              "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
              "open_issues": 61,
              "open_issues_count": 61,
              "owner": {
                "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
                "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
                "followers_url": "https://api.github.com/users/graphql-hive/followers",
                "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
                "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
                "gravatar_id": "",
                "html_url": "https://github.com/graphql-hive",
                "id": 182742256,
                "login": "graphql-hive",
                "node_id": "O_kgDOCuRs8A",
                "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
                "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
                "repos_url": "https://api.github.com/users/graphql-hive/repos",
                "site_admin": false,
                "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
                "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
                "type": "Organization",
                "url": "https://api.github.com/users/graphql-hive",
                "user_view_type": "public"
              },
              "private": false,
              "pull_request_creation_policy": "all",
              "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
              "pushed_at": "2026-03-24T09:34:00Z",
              "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
              "size": 5903,
              "squash_merge_commit_message": "PR_BODY",
              "squash_merge_commit_title": "PR_TITLE",
              "ssh_url": "git@github.com:graphql-hive/router.git",
              "stargazers_count": 79,
              "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
              "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
              "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
              "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
              "svn_url": "https://github.com/graphql-hive/router",
              "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
              "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
              "topics": [
                "apollo-federation",
                "federation",
                "federation-gateway",
                "graphql",
                "graphql-federation",
                "router"
              ],
              "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
              "updated_at": "2026-03-24T00:29:34Z",
              "url": "https://api.github.com/repos/graphql-hive/router",
              "use_squash_pr_title_as_default": true,
              "visibility": "public",
              "watchers": 79,
              "watchers_count": 79,
              "web_commit_signoff_required": false
            },
            "sha": "e197521774a40772c629fd3d37d40d532be6c965",
            "user": {
              "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
              "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
              "followers_url": "https://api.github.com/users/graphql-hive/followers",
              "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
              "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/graphql-hive",
              "id": 182742256,
              "login": "graphql-hive",
              "node_id": "O_kgDOCuRs8A",
              "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
              "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
              "repos_url": "https://api.github.com/users/graphql-hive/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
              "type": "Organization",
              "url": "https://api.github.com/users/graphql-hive",
              "user_view_type": "public"
            }
          },
          "html_url": "https://github.com/graphql-hive/router/pull/865",
          "id": 3415271595,
          "issue_url": "https://api.github.com/repos/graphql-hive/router/issues/865",
          "labels": [],
          "locked": false,
          "maintainer_can_modify": false,
          "merge_commit_sha": "80f39fc394ea101635bf2c5be1a827e56c45f830",
          "mergeable": null,
          "mergeable_state": "unknown",
          "merged": false,
          "merged_at": null,
          "merged_by": null,
          "milestone": null,
          "node_id": "PR_kwDONSTNFM7LkOir",
          "number": 865,
          "patch_url": "https://github.com/graphql-hive/router/pull/865.patch",
          "rebaseable": null,
          "requested_reviewers": [
            {
              "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
              "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
              "followers_url": "https://api.github.com/users/kamilkisiela/followers",
              "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
              "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/kamilkisiela",
              "id": 8167190,
              "login": "kamilkisiela",
              "node_id": "MDQ6VXNlcjgxNjcxOTA=",
              "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
              "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
              "repos_url": "https://api.github.com/users/kamilkisiela/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/kamilkisiela",
              "user_view_type": "public"
            }
          ],
          "requested_teams": [],
          "review_comment_url": "https://api.github.com/repos/graphql-hive/router/pulls/comments{/number}",
          "review_comments": 0,
          "review_comments_url": "https://api.github.com/repos/graphql-hive/router/pulls/865/comments",
          "state": "open",
          "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/e197521774a40772c629fd3d37d40d532be6c965",
          "title": "Replace direct `ryu` usage with `zmij` for float formatting",
          "updated_at": "2026-03-24T09:34:02Z",
          "url": "https://api.github.com/repos/graphql-hive/router/pulls/865",
          "user": {
            "avatar_url": "https://avatars.githubusercontent.com/in/1143301?v=4",
            "events_url": "https://api.github.com/users/Copilot/events{/privacy}",
            "followers_url": "https://api.github.com/users/Copilot/followers",
            "following_url": "https://api.github.com/users/Copilot/following{/other_user}",
            "gists_url": "https://api.github.com/users/Copilot/gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/apps/copilot-swe-agent",
            "id": 198982749,
            "login": "Copilot",
            "node_id": "BOT_kgDOC9w8XQ",
            "organizations_url": "https://api.github.com/users/Copilot/orgs",
            "received_events_url": "https://api.github.com/users/Copilot/received_events",
            "repos_url": "https://api.github.com/users/Copilot/repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users/Copilot/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/Copilot/subscriptions",
            "type": "Bot",
            "url": "https://api.github.com/users/Copilot",
            "user_view_type": "public"
          }
        },
        "repository": {
          "allow_forking": true,
          "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
          "archived": false,
          "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
          "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
          "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
          "clone_url": "https://github.com/graphql-hive/router.git",
          "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
          "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
          "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
          "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
          "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
          "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
          "created_at": "2024-11-20T16:16:12Z",
          "custom_properties": {
            "vanta_production_branch_name": "main"
          },
          "default_branch": "main",
          "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
          "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
          "disabled": false,
          "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
          "events_url": "https://api.github.com/repos/graphql-hive/router/events",
          "fork": false,
          "forks": 9,
          "forks_count": 9,
          "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
          "full_name": "graphql-hive/router",
          "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
          "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
          "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
          "git_url": "git://github.com/graphql-hive/router.git",
          "has_discussions": false,
          "has_downloads": true,
          "has_issues": true,
          "has_pages": false,
          "has_projects": false,
          "has_pull_requests": true,
          "has_wiki": false,
          "homepage": "https://the-guild.dev/graphql/hive/docs/router",
          "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
          "html_url": "https://github.com/graphql-hive/router",
          "id": 891604244,
          "is_template": false,
          "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
          "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
          "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
          "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
          "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
          "language": "Rust",
          "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
          "license": {
            "key": "mit",
            "name": "MIT License",
            "node_id": "MDc6TGljZW5zZTEz",
            "spdx_id": "MIT",
            "url": "https://api.github.com/licenses/mit"
          },
          "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
          "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
          "mirror_url": null,
          "name": "router",
          "node_id": "R_kgDONSTNFA",
          "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
          "open_issues": 61,
          "open_issues_count": 61,
          "owner": {
            "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
            "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
            "followers_url": "https://api.github.com/users/graphql-hive/followers",
            "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
            "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/graphql-hive",
            "id": 182742256,
            "login": "graphql-hive",
            "node_id": "O_kgDOCuRs8A",
            "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
            "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
            "repos_url": "https://api.github.com/users/graphql-hive/repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
            "type": "Organization",
            "url": "https://api.github.com/users/graphql-hive",
            "user_view_type": "public"
          },
          "private": false,
          "pull_request_creation_policy": "all",
          "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
          "pushed_at": "2026-03-24T09:34:00Z",
          "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
          "size": 5903,
          "ssh_url": "git@github.com:graphql-hive/router.git",
          "stargazers_count": 79,
          "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
          "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
          "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
          "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
          "svn_url": "https://github.com/graphql-hive/router",
          "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
          "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
          "topics": [
            "apollo-federation",
            "federation",
            "federation-gateway",
            "graphql",
            "graphql-federation",
            "router"
          ],
          "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
          "updated_at": "2026-03-24T00:29:34Z",
          "url": "https://api.github.com/repos/graphql-hive/router",
          "visibility": "public",
          "watchers": 79,
          "watchers_count": 79,
          "web_commit_signoff_required": false
        },
        "sender": {
          "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
          "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
          "followers_url": "https://api.github.com/users/kamilkisiela/followers",
          "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
          "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
          "gravatar_id": "",
          "html_url": "https://github.com/kamilkisiela",
          "id": 8167190,
          "login": "kamilkisiela",
          "node_id": "MDQ6VXNlcjgxNjcxOTA=",
          "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
          "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
          "repos_url": "https://api.github.com/users/kamilkisiela/repos",
          "site_admin": false,
          "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
          "type": "User",
          "url": "https://api.github.com/users/kamilkisiela",
          "user_view_type": "public"
        }
      },
      "github_job": "docker",
      "github_ref": "refs/pull/865/merge",
      "github_ref_name": "865/merge",
      "github_ref_protected": "false",
      "github_ref_type": "branch",
      "github_repository": "graphql-hive/router",
      "github_repository_id": "891604244",
      "github_repository_owner": "graphql-hive",
      "github_repository_owner_id": "182742256",
      "github_run_attempt": "1",
      "github_run_id": "23482584243",
      "github_run_number": "2071",
      "github_runner_arch": "X64",
      "github_runner_environment": "github-hosted",
      "github_runner_image_os": "ubuntu24",
      "github_runner_image_version": "20260309.50.1",
      "github_runner_name": "GitHub Actions 1000684234",
      "github_runner_os": "Linux",
      "github_runner_tracking_id": "github_3ae3ac00-faac-4903-8640-18814519786a",
      "github_server_url": "https://github.com",
      "github_triggering_actor": "kamilkisiela",
      "github_workflow": "build-router",
      "github_workflow_ref": "graphql-hive/router/.github/workflows/build-router.yaml@refs/pull/865/merge",
      "github_workflow_sha": "20e5cb2f06fd49b83463db35b8ba8fbe263fb399",
      "platform": "linux/amd64"
    }
  }
},
"buildx.build.provenance/linux/arm64": {
  "builder": {
    "id": "https://github.com/graphql-hive/router/actions/runs/23482584243/attempts/1"
  },
  "buildType": "https://mobyproject.org/buildkit@v1",
  "materials": [
    {
      "uri": "pkg:docker/docker/dockerfile@1.22",
      "digest": {
        "sha256": "4a43a54dd1fedceb30ba47e76cfcf2b47304f4161c0caeac2db1c61804ea3c91"
      }
    },
    {
      "uri": "pkg:docker/gcr.io/distroless/cc-debian12@latest?platform=linux%2Farm64",
      "digest": {
        "sha256": "329e54034ce498f9c6b345044e8f530c6691f99e94a92446f68c0adf9baa8464"
      }
    }
  ],
  "invocation": {
    "configSource": {
      "entryPoint": "router.Dockerfile"
    },
    "parameters": {
      "frontend": "gateway.v0",
      "args": {
        "cmdline": "docker/dockerfile:1.22",
        "label:org.opencontainers.image.created": "2026-03-24T09:47:12.991Z",
        "label:org.opencontainers.image.description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
        "label:org.opencontainers.image.licenses": "MIT",
        "label:org.opencontainers.image.revision": "20e5cb2f06fd49b83463db35b8ba8fbe263fb399",
        "label:org.opencontainers.image.source": "https://github.com/graphql-hive/router",
        "label:org.opencontainers.image.title": "router",
        "label:org.opencontainers.image.url": "https://github.com/graphql-hive/router",
        "label:org.opencontainers.image.vendor": "theguild",
        "label:org.opencontainers.image.version": "pr-865",
        "source": "docker/dockerfile:1.22"
      },
      "locals": [
        {
          "name": "context"
        },
        {
          "name": "dockerfile"
        }
      ]
    },
    "environment": {
      "github_actor": "kamilkisiela",
      "github_actor_id": "8167190",
      "github_event_name": "pull_request",
      "github_event_payload": {
        "action": "synchronize",
        "after": "e197521774a40772c629fd3d37d40d532be6c965",
        "before": "40fa07a5b841199e4a8e201554fd5e62a10a66fc",
        "enterprise": {
          "avatar_url": "https://avatars.githubusercontent.com/b/187753?v=4",
          "created_at": "2024-07-02T08:52:28Z",
          "description": "",
          "html_url": "https://github.com/enterprises/the-guild",
          "id": 187753,
          "name": "The Guild",
          "node_id": "E_kgDOAALdaQ",
          "slug": "the-guild",
          "updated_at": "2026-03-11T16:47:15Z",
          "website_url": "https://the-guild.dev/"
        },
        "number": 865,
        "organization": {
          "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
          "description": "Schema registry, analytics and gateway for GraphQL federation and other GraphQL APIs.",
          "events_url": "https://api.github.com/orgs/graphql-hive/events",
          "hooks_url": "https://api.github.com/orgs/graphql-hive/hooks",
          "id": 182742256,
          "issues_url": "https://api.github.com/orgs/graphql-hive/issues",
          "login": "graphql-hive",
          "members_url": "https://api.github.com/orgs/graphql-hive/members{/member}",
          "node_id": "O_kgDOCuRs8A",
          "public_members_url": "https://api.github.com/orgs/graphql-hive/public_members{/member}",
          "repos_url": "https://api.github.com/orgs/graphql-hive/repos",
          "url": "https://api.github.com/orgs/graphql-hive"
        },
        "pull_request": {
          "_links": {
            "comments": {
              "href": "https://api.github.com/repos/graphql-hive/router/issues/865/comments"
            },
            "commits": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865/commits"
            },
            "html": {
              "href": "https://github.com/graphql-hive/router/pull/865"
            },
            "issue": {
              "href": "https://api.github.com/repos/graphql-hive/router/issues/865"
            },
            "review_comment": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/comments{/number}"
            },
            "review_comments": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865/comments"
            },
            "self": {
              "href": "https://api.github.com/repos/graphql-hive/router/pulls/865"
            },
            "statuses": {
              "href": "https://api.github.com/repos/graphql-hive/router/statuses/e197521774a40772c629fd3d37d40d532be6c965"
            }
          },
          "active_lock_reason": null,
          "additions": 29,
          "assignee": null,
          "assignees": [
            {
              "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
              "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
              "followers_url": "https://api.github.com/users/kamilkisiela/followers",
              "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
              "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/kamilkisiela",
              "id": 8167190,
              "login": "kamilkisiela",
              "node_id": "MDQ6VXNlcjgxNjcxOTA=",
              "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
              "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
              "repos_url": "https://api.github.com/users/kamilkisiela/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/kamilkisiela",
              "user_view_type": "public"
            },
            {
              "avatar_url": "https://avatars.githubusercontent.com/in/1143301?v=4",
              "events_url": "https://api.github.com/users/Copilot/events{/privacy}",
              "followers_url": "https://api.github.com/users/Copilot/followers",
              "following_url": "https://api.github.com/users/Copilot/following{/other_user}",
              "gists_url": "https://api.github.com/users/Copilot/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/apps/copilot-swe-agent",
              "id": 198982749,
              "login": "Copilot",
              "node_id": "BOT_kgDOC9w8XQ",
              "organizations_url": "https://api.github.com/users/Copilot/orgs",
              "received_events_url": "https://api.github.com/users/Copilot/received_events",
              "repos_url": "https://api.github.com/users/Copilot/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/Copilot/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/Copilot/subscriptions",
              "type": "Bot",
              "url": "https://api.github.com/users/Copilot",
              "user_view_type": "public"
            }
          ],
          "author_association": "NONE",
          "auto_merge": null,
          "base": {
            "label": "graphql-hive:main",
            "ref": "main",
            "repo": {
              "allow_auto_merge": false,
              "allow_forking": true,
              "allow_merge_commit": false,
              "allow_rebase_merge": false,
              "allow_squash_merge": true,
              "allow_update_branch": true,
              "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
              "archived": false,
              "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
              "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
              "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
              "clone_url": "https://github.com/graphql-hive/router.git",
              "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
              "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
              "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
              "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
              "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
              "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
              "created_at": "2024-11-20T16:16:12Z",
              "default_branch": "main",
              "delete_branch_on_merge": true,
              "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
              "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
              "disabled": false,
              "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
              "events_url": "https://api.github.com/repos/graphql-hive/router/events",
              "fork": false,
              "forks": 9,
              "forks_count": 9,
              "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
              "full_name": "graphql-hive/router",
              "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
              "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
              "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
              "git_url": "git://github.com/graphql-hive/router.git",
              "has_discussions": false,
              "has_downloads": true,
              "has_issues": true,
              "has_pages": false,
              "has_projects": false,
              "has_pull_requests": true,
              "has_wiki": false,
              "homepage": "https://the-guild.dev/graphql/hive/docs/router",
              "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
              "html_url": "https://github.com/graphql-hive/router",
              "id": 891604244,
              "is_template": false,
              "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
              "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
              "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
              "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
              "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
              "language": "Rust",
              "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
              "license": {
                "key": "mit",
                "name": "MIT License",
                "node_id": "MDc6TGljZW5zZTEz",
                "spdx_id": "MIT",
                "url": "https://api.github.com/licenses/mit"
              },
              "merge_commit_message": "PR_TITLE",
              "merge_commit_title": "MERGE_MESSAGE",
              "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
              "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
              "mirror_url": null,
              "name": "router",
              "node_id": "R_kgDONSTNFA",
              "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
              "open_issues": 61,
              "open_issues_count": 61,
              "owner": {
                "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
                "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
                "followers_url": "https://api.github.com/users/graphql-hive/followers",
                "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
                "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
                "gravatar_id": "",
                "html_url": "https://github.com/graphql-hive",
                "id": 182742256,
                "login": "graphql-hive",
                "node_id": "O_kgDOCuRs8A",
                "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
                "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
                "repos_url": "https://api.github.com/users/graphql-hive/repos",
                "site_admin": false,
                "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
                "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
                "type": "Organization",
                "url": "https://api.github.com/users/graphql-hive",
                "user_view_type": "public"
              },
              "private": false,
              "pull_request_creation_policy": "all",
              "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
              "pushed_at": "2026-03-24T09:34:00Z",
              "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
              "size": 5903,
              "squash_merge_commit_message": "PR_BODY",
              "squash_merge_commit_title": "PR_TITLE",
              "ssh_url": "git@github.com:graphql-hive/router.git",
              "stargazers_count": 79,
              "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
              "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
              "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
              "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
              "svn_url": "https://github.com/graphql-hive/router",
              "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
              "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
              "topics": [
                "apollo-federation",
                "federation",
                "federation-gateway",
                "graphql",
                "graphql-federation",
                "router"
              ],
              "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
              "updated_at": "2026-03-24T00:29:34Z",
              "url": "https://api.github.com/repos/graphql-hive/router",
              "use_squash_pr_title_as_default": true,
              "visibility": "public",
              "watchers": 79,
              "watchers_count": 79,
              "web_commit_signoff_required": false
            },
            "sha": "2522e961a6dca22ad4417a9deefe306eabb2c614",
            "user": {
              "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
              "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
              "followers_url": "https://api.github.com/users/graphql-hive/followers",
              "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
              "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/graphql-hive",
              "id": 182742256,
              "login": "graphql-hive",
              "node_id": "O_kgDOCuRs8A",
              "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
              "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
              "repos_url": "https://api.github.com/users/graphql-hive/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
              "type": "Organization",
              "url": "https://api.github.com/users/graphql-hive",
              "user_view_type": "public"
            }
          },
          "body": "This change replaces direct `ryu` usage with `zmij` in the router codepaths that serialize floating-point values. The goal is to align float-to-string formatting with `zmij` while preserving existing output behavior.\n\n- **Dependency updates**\n  - Swapped direct crate dependencies:\n    - `lib/graphql-tools/Cargo.toml`: `ryu` → `zmij`\n    - `lib/executor/Cargo.toml`: `ryu` → `zmij`\n  - Updated lockfile edges so affected crates now resolve through `zmij`.\n\n- **Runtime formatting path migration**\n  - Updated GraphQL AST minification float formatting:\n    - `lib/graphql-tools/src/parser/query/minify.rs`\n    - `ryu::Buffer` replaced with `zmij::Buffer`.\n  - Updated JSON float writer in plan executor:\n    - `lib/executor/src/json_writer.rs`\n    - `ryu::Buffer` replaced with `zmij::Buffer`.\n\n- **Documentation/comments consistency**\n  - Updated in-code comments in minifier implementation to reference `zmij` instead of `ryu`.\n\n- **Focused regression coverage**\n  - Added targeted tests in `lib/executor/src/json_writer.rs` for:\n    - finite float serialization\n    - non-finite float (`NaN`) serialization to `null`\n\nExample of the core migration:\n\n```rust\nlet mut buffer = zmij::Buffer::new();\nlet s = buffer.format_finite(value);\nwriter.put(s.as_bytes());\n```\n\n<!-- START COPILOT CODING AGENT TIPS -->\n---\n\n💬 Send tasks to Copilot coding agent from [Slack](https://gh.io/cca-slack-docs) and [Teams](https://gh.io/cca-teams-docs) to turn conversations into code. Copilot posts an update in your thread when it's finished.",
          "changed_files": 5,
          "closed_at": null,
          "comments": 1,
          "comments_url": "https://api.github.com/repos/graphql-hive/router/issues/865/comments",
          "commits": 1,
          "commits_url": "https://api.github.com/repos/graphql-hive/router/pulls/865/commits",
          "created_at": "2026-03-18T14:42:51Z",
          "deletions": 11,
          "diff_url": "https://github.com/graphql-hive/router/pull/865.diff",
          "draft": true,
          "head": {
            "label": "graphql-hive:copilot/replace-ryu-with-zmij",
            "ref": "copilot/replace-ryu-with-zmij",
            "repo": {
              "allow_auto_merge": false,
              "allow_forking": true,
              "allow_merge_commit": false,
              "allow_rebase_merge": false,
              "allow_squash_merge": true,
              "allow_update_branch": true,
              "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
              "archived": false,
              "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
              "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
              "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
              "clone_url": "https://github.com/graphql-hive/router.git",
              "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
              "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
              "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
              "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
              "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
              "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
              "created_at": "2024-11-20T16:16:12Z",
              "default_branch": "main",
              "delete_branch_on_merge": true,
              "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
              "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
              "disabled": false,
              "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
              "events_url": "https://api.github.com/repos/graphql-hive/router/events",
              "fork": false,
              "forks": 9,
              "forks_count": 9,
              "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
              "full_name": "graphql-hive/router",
              "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
              "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
              "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
              "git_url": "git://github.com/graphql-hive/router.git",
              "has_discussions": false,
              "has_downloads": true,
              "has_issues": true,
              "has_pages": false,
              "has_projects": false,
              "has_pull_requests": true,
              "has_wiki": false,
              "homepage": "https://the-guild.dev/graphql/hive/docs/router",
              "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
              "html_url": "https://github.com/graphql-hive/router",
              "id": 891604244,
              "is_template": false,
              "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
              "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
              "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
              "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
              "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
              "language": "Rust",
              "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
              "license": {
                "key": "mit",
                "name": "MIT License",
                "node_id": "MDc6TGljZW5zZTEz",
                "spdx_id": "MIT",
                "url": "https://api.github.com/licenses/mit"
              },
              "merge_commit_message": "PR_TITLE",
              "merge_commit_title": "MERGE_MESSAGE",
              "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
              "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
              "mirror_url": null,
              "name": "router",
              "node_id": "R_kgDONSTNFA",
              "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
              "open_issues": 61,
              "open_issues_count": 61,
              "owner": {
                "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
                "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
                "followers_url": "https://api.github.com/users/graphql-hive/followers",
                "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
                "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
                "gravatar_id": "",
                "html_url": "https://github.com/graphql-hive",
                "id": 182742256,
                "login": "graphql-hive",
                "node_id": "O_kgDOCuRs8A",
                "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
                "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
                "repos_url": "https://api.github.com/users/graphql-hive/repos",
                "site_admin": false,
                "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
                "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
                "type": "Organization",
                "url": "https://api.github.com/users/graphql-hive",
                "user_view_type": "public"
              },
              "private": false,
              "pull_request_creation_policy": "all",
              "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
              "pushed_at": "2026-03-24T09:34:00Z",
              "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
              "size": 5903,
              "squash_merge_commit_message": "PR_BODY",
              "squash_merge_commit_title": "PR_TITLE",
              "ssh_url": "git@github.com:graphql-hive/router.git",
              "stargazers_count": 79,
              "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
              "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
              "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
              "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
              "svn_url": "https://github.com/graphql-hive/router",
              "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
              "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
              "topics": [
                "apollo-federation",
                "federation",
                "federation-gateway",
                "graphql",
                "graphql-federation",
                "router"
              ],
              "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
              "updated_at": "2026-03-24T00:29:34Z",
              "url": "https://api.github.com/repos/graphql-hive/router",
              "use_squash_pr_title_as_default": true,
              "visibility": "public",
              "watchers": 79,
              "watchers_count": 79,
              "web_commit_signoff_required": false
            },
            "sha": "e197521774a40772c629fd3d37d40d532be6c965",
            "user": {
              "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
              "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
              "followers_url": "https://api.github.com/users/graphql-hive/followers",
              "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
              "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/graphql-hive",
              "id": 182742256,
              "login": "graphql-hive",
              "node_id": "O_kgDOCuRs8A",
              "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
              "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
              "repos_url": "https://api.github.com/users/graphql-hive/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
              "type": "Organization",
              "url": "https://api.github.com/users/graphql-hive",
              "user_view_type": "public"
            }
          },
          "html_url": "https://github.com/graphql-hive/router/pull/865",
          "id": 3415271595,
          "issue_url": "https://api.github.com/repos/graphql-hive/router/issues/865",
          "labels": [],
          "locked": false,
          "maintainer_can_modify": false,
          "merge_commit_sha": "80f39fc394ea101635bf2c5be1a827e56c45f830",
          "mergeable": null,
          "mergeable_state": "unknown",
          "merged": false,
          "merged_at": null,
          "merged_by": null,
          "milestone": null,
          "node_id": "PR_kwDONSTNFM7LkOir",
          "number": 865,
          "patch_url": "https://github.com/graphql-hive/router/pull/865.patch",
          "rebaseable": null,
          "requested_reviewers": [
            {
              "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
              "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
              "followers_url": "https://api.github.com/users/kamilkisiela/followers",
              "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
              "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
              "gravatar_id": "",
              "html_url": "https://github.com/kamilkisiela",
              "id": 8167190,
              "login": "kamilkisiela",
              "node_id": "MDQ6VXNlcjgxNjcxOTA=",
              "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
              "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
              "repos_url": "https://api.github.com/users/kamilkisiela/repos",
              "site_admin": false,
              "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
              "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
              "type": "User",
              "url": "https://api.github.com/users/kamilkisiela",
              "user_view_type": "public"
            }
          ],
          "requested_teams": [],
          "review_comment_url": "https://api.github.com/repos/graphql-hive/router/pulls/comments{/number}",
          "review_comments": 0,
          "review_comments_url": "https://api.github.com/repos/graphql-hive/router/pulls/865/comments",
          "state": "open",
          "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/e197521774a40772c629fd3d37d40d532be6c965",
          "title": "Replace direct `ryu` usage with `zmij` for float formatting",
          "updated_at": "2026-03-24T09:34:02Z",
          "url": "https://api.github.com/repos/graphql-hive/router/pulls/865",
          "user": {
            "avatar_url": "https://avatars.githubusercontent.com/in/1143301?v=4",
            "events_url": "https://api.github.com/users/Copilot/events{/privacy}",
            "followers_url": "https://api.github.com/users/Copilot/followers",
            "following_url": "https://api.github.com/users/Copilot/following{/other_user}",
            "gists_url": "https://api.github.com/users/Copilot/gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/apps/copilot-swe-agent",
            "id": 198982749,
            "login": "Copilot",
            "node_id": "BOT_kgDOC9w8XQ",
            "organizations_url": "https://api.github.com/users/Copilot/orgs",
            "received_events_url": "https://api.github.com/users/Copilot/received_events",
            "repos_url": "https://api.github.com/users/Copilot/repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users/Copilot/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/Copilot/subscriptions",
            "type": "Bot",
            "url": "https://api.github.com/users/Copilot",
            "user_view_type": "public"
          }
        },
        "repository": {
          "allow_forking": true,
          "archive_url": "https://api.github.com/repos/graphql-hive/router/{archive_format}{/ref}",
          "archived": false,
          "assignees_url": "https://api.github.com/repos/graphql-hive/router/assignees{/user}",
          "blobs_url": "https://api.github.com/repos/graphql-hive/router/git/blobs{/sha}",
          "branches_url": "https://api.github.com/repos/graphql-hive/router/branches{/branch}",
          "clone_url": "https://github.com/graphql-hive/router.git",
          "collaborators_url": "https://api.github.com/repos/graphql-hive/router/collaborators{/collaborator}",
          "comments_url": "https://api.github.com/repos/graphql-hive/router/comments{/number}",
          "commits_url": "https://api.github.com/repos/graphql-hive/router/commits{/sha}",
          "compare_url": "https://api.github.com/repos/graphql-hive/router/compare/{base}...{head}",
          "contents_url": "https://api.github.com/repos/graphql-hive/router/contents/{+path}",
          "contributors_url": "https://api.github.com/repos/graphql-hive/router/contributors",
          "created_at": "2024-11-20T16:16:12Z",
          "custom_properties": {
            "vanta_production_branch_name": "main"
          },
          "default_branch": "main",
          "deployments_url": "https://api.github.com/repos/graphql-hive/router/deployments",
          "description": "Open-source (MIT) GraphQL Federation Router. Built with Rust for maximum performance and robustness.",
          "disabled": false,
          "downloads_url": "https://api.github.com/repos/graphql-hive/router/downloads",
          "events_url": "https://api.github.com/repos/graphql-hive/router/events",
          "fork": false,
          "forks": 9,
          "forks_count": 9,
          "forks_url": "https://api.github.com/repos/graphql-hive/router/forks",
          "full_name": "graphql-hive/router",
          "git_commits_url": "https://api.github.com/repos/graphql-hive/router/git/commits{/sha}",
          "git_refs_url": "https://api.github.com/repos/graphql-hive/router/git/refs{/sha}",
          "git_tags_url": "https://api.github.com/repos/graphql-hive/router/git/tags{/sha}",
          "git_url": "git://github.com/graphql-hive/router.git",
          "has_discussions": false,
          "has_downloads": true,
          "has_issues": true,
          "has_pages": false,
          "has_projects": false,
          "has_pull_requests": true,
          "has_wiki": false,
          "homepage": "https://the-guild.dev/graphql/hive/docs/router",
          "hooks_url": "https://api.github.com/repos/graphql-hive/router/hooks",
          "html_url": "https://github.com/graphql-hive/router",
          "id": 891604244,
          "is_template": false,
          "issue_comment_url": "https://api.github.com/repos/graphql-hive/router/issues/comments{/number}",
          "issue_events_url": "https://api.github.com/repos/graphql-hive/router/issues/events{/number}",
          "issues_url": "https://api.github.com/repos/graphql-hive/router/issues{/number}",
          "keys_url": "https://api.github.com/repos/graphql-hive/router/keys{/key_id}",
          "labels_url": "https://api.github.com/repos/graphql-hive/router/labels{/name}",
          "language": "Rust",
          "languages_url": "https://api.github.com/repos/graphql-hive/router/languages",
          "license": {
            "key": "mit",
            "name": "MIT License",
            "node_id": "MDc6TGljZW5zZTEz",
            "spdx_id": "MIT",
            "url": "https://api.github.com/licenses/mit"
          },
          "merges_url": "https://api.github.com/repos/graphql-hive/router/merges",
          "milestones_url": "https://api.github.com/repos/graphql-hive/router/milestones{/number}",
          "mirror_url": null,
          "name": "router",
          "node_id": "R_kgDONSTNFA",
          "notifications_url": "https://api.github.com/repos/graphql-hive/router/notifications{?since,all,participating}",
          "open_issues": 61,
          "open_issues_count": 61,
          "owner": {
            "avatar_url": "https://avatars.githubusercontent.com/u/182742256?v=4",
            "events_url": "https://api.github.com/users/graphql-hive/events{/privacy}",
            "followers_url": "https://api.github.com/users/graphql-hive/followers",
            "following_url": "https://api.github.com/users/graphql-hive/following{/other_user}",
            "gists_url": "https://api.github.com/users/graphql-hive/gists{/gist_id}",
            "gravatar_id": "",
            "html_url": "https://github.com/graphql-hive",
            "id": 182742256,
            "login": "graphql-hive",
            "node_id": "O_kgDOCuRs8A",
            "organizations_url": "https://api.github.com/users/graphql-hive/orgs",
            "received_events_url": "https://api.github.com/users/graphql-hive/received_events",
            "repos_url": "https://api.github.com/users/graphql-hive/repos",
            "site_admin": false,
            "starred_url": "https://api.github.com/users/graphql-hive/starred{/owner}{/repo}",
            "subscriptions_url": "https://api.github.com/users/graphql-hive/subscriptions",
            "type": "Organization",
            "url": "https://api.github.com/users/graphql-hive",
            "user_view_type": "public"
          },
          "private": false,
          "pull_request_creation_policy": "all",
          "pulls_url": "https://api.github.com/repos/graphql-hive/router/pulls{/number}",
          "pushed_at": "2026-03-24T09:34:00Z",
          "releases_url": "https://api.github.com/repos/graphql-hive/router/releases{/id}",
          "size": 5903,
          "ssh_url": "git@github.com:graphql-hive/router.git",
          "stargazers_count": 79,
          "stargazers_url": "https://api.github.com/repos/graphql-hive/router/stargazers",
          "statuses_url": "https://api.github.com/repos/graphql-hive/router/statuses/{sha}",
          "subscribers_url": "https://api.github.com/repos/graphql-hive/router/subscribers",
          "subscription_url": "https://api.github.com/repos/graphql-hive/router/subscription",
          "svn_url": "https://github.com/graphql-hive/router",
          "tags_url": "https://api.github.com/repos/graphql-hive/router/tags",
          "teams_url": "https://api.github.com/repos/graphql-hive/router/teams",
          "topics": [
            "apollo-federation",
            "federation",
            "federation-gateway",
            "graphql",
            "graphql-federation",
            "router"
          ],
          "trees_url": "https://api.github.com/repos/graphql-hive/router/git/trees{/sha}",
          "updated_at": "2026-03-24T00:29:34Z",
          "url": "https://api.github.com/repos/graphql-hive/router",
          "visibility": "public",
          "watchers": 79,
          "watchers_count": 79,
          "web_commit_signoff_required": false
        },
        "sender": {
          "avatar_url": "https://avatars.githubusercontent.com/u/8167190?v=4",
          "events_url": "https://api.github.com/users/kamilkisiela/events{/privacy}",
          "followers_url": "https://api.github.com/users/kamilkisiela/followers",
          "following_url": "https://api.github.com/users/kamilkisiela/following{/other_user}",
          "gists_url": "https://api.github.com/users/kamilkisiela/gists{/gist_id}",
          "gravatar_id": "",
          "html_url": "https://github.com/kamilkisiela",
          "id": 8167190,
          "login": "kamilkisiela",
          "node_id": "MDQ6VXNlcjgxNjcxOTA=",
          "organizations_url": "https://api.github.com/users/kamilkisiela/orgs",
          "received_events_url": "https://api.github.com/users/kamilkisiela/received_events",
          "repos_url": "https://api.github.com/users/kamilkisiela/repos",
          "site_admin": false,
          "starred_url": "https://api.github.com/users/kamilkisiela/starred{/owner}{/repo}",
          "subscriptions_url": "https://api.github.com/users/kamilkisiela/subscriptions",
          "type": "User",
          "url": "https://api.github.com/users/kamilkisiela",
          "user_view_type": "public"
        }
      },
      "github_job": "docker",
      "github_ref": "refs/pull/865/merge",
      "github_ref_name": "865/merge",
      "github_ref_protected": "false",
      "github_ref_type": "branch",
      "github_repository": "graphql-hive/router",
      "github_repository_id": "891604244",
      "github_repository_owner": "graphql-hive",
      "github_repository_owner_id": "182742256",
      "github_run_attempt": "1",
      "github_run_id": "23482584243",
      "github_run_number": "2071",
      "github_runner_arch": "X64",
      "github_runner_environment": "github-hosted",
      "github_runner_image_os": "ubuntu24",
      "github_runner_image_version": "20260309.50.1",
      "github_runner_name": "GitHub Actions 1000684234",
      "github_runner_os": "Linux",
      "github_runner_tracking_id": "github_3ae3ac00-faac-4903-8640-18814519786a",
      "github_server_url": "https://github.com",
      "github_triggering_actor": "kamilkisiela",
      "github_workflow": "build-router",
      "github_workflow_ref": "graphql-hive/router/.github/workflows/build-router.yaml@refs/pull/865/merge",
      "github_workflow_sha": "20e5cb2f06fd49b83463db35b8ba8fbe263fb399",
      "platform": "linux/amd64"
    }
  }
},
"buildx.build.ref": "builder-40093666-09b9-4d18-8f0a-bf29b11bcad7/builder-40093666-09b9-4d18-8f0a-bf29b11bcad70/w60qe50c9ceu47ryvso9mshx0",
"containerimage.descriptor": {
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "digest": "sha256:cec0f1d0f763e02cf9096851b5e0c90143fbec3690fbb68ad21a773f5a18f767",
  "size": 1609
},
"containerimage.digest": "sha256:cec0f1d0f763e02cf9096851b5e0c90143fbec3690fbb68ad21a773f5a18f767",
"image.name": "ghcr.io/graphql-hive/router:pr-865,ghcr.io/graphql-hive/router:sha-20e5cb2"
}

Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
@kamilkisiela kamilkisiela force-pushed the copilot/replace-ryu-with-zmij branch from 40fa07a to e197521 Compare March 24, 2026 09:34
@kamilkisiela
Copy link
Copy Markdown
Contributor

@copilot rebase and add a changeset (patch)

kamilkisiela and others added 2 commits March 24, 2026 11:52
- Add inbound router request deduplication for concurrent identical
GraphQL requests, with atomic in-flight key claiming and leader/joiner
response sharing.
- Feature behind `traffic_shaping.router.dedupe.enabled` (default: false
- but I'm open to change it. I made it 'all' and disabled by default as
anything that makes a request "unique" affects the request fingerprint
and therefore deduplication), and include current schema checksum in the
dedupe fingerprint to prevent cross-schema sharing.
- Restrict response sharing to `query` operations only

```yaml
traffic_shaping:
  router:
    dedupe:
      enabled: true # default
      headers: all # default
```

---

The deduplication key is built out of:
- request method and path
- selected request headers (based on dedupe header policy - see examples
below)
- normalized operation hash
- GraphQL variables hash
- GraphQL extensions hash
- schema checksum

Header policy: include all headers in the req fingerprint
```yaml
headers: all
```

Header policy: do not include headers in the req fingerprint
```yaml
headers: none
```

Header policy: include only some headers in the req fingerprint
```yaml
headers:
  include:
    - authorization
    - cookie
```

Docs: graphql-hive/docs#62
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Agent-Logs-Url: https://github.com/graphql-hive/router/sessions/697ee76f-0b27-4111-9902-61d62a29e7b7
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot rebase and add a changeset (patch)

Done — I rebased this branch on top of latest main and added a patch changeset at .changeset/replace-ryu-with-zmij.md in commit d2e46f4.

@enisdenjo enisdenjo force-pushed the main branch 3 times, most recently from 511f910 to e09e78a Compare April 1, 2026 19:17
@kamilkisiela
Copy link
Copy Markdown
Contributor

@copilot rebase

dotansimha and others added 10 commits May 5, 2026 14:39
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
add a dedicated benchmark config and CI scenario for inbound
deduplication so it can be compared explicitly with `main`.

the `default` and `plugins` benchmark configs no longer enable inbound
deduplication, and the inbound-dedupe case now lives in its own
`dedupe-inbound` config.

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/graphql-hive/router/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…ction is disabled (#872)

Related: #871 

Closes ROUTER-278
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
… prevent malformed JSON (#881)

Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Closes ROUTER-279
Closes: #876  

# Generating conflicting aliases when conflicts are across fragments

Consider a schema like:
```graphql
interface CommonInterface {
  id: ID!
}

type TypeA implements CommonInterface {
  id: ID!
  field: EnumA!
}

type TypeB implements CommonInterface {
  id: ID!
  field: EnumB!
}

type TypeC implements CommonInterface {
  id: ID!
  field: EnumC!
}

enum EnumA { VALUE_A1  VALUE_A2  VALUE_A3 }
enum EnumB { VALUE_B1  VALUE_B2  VALUE_B3 }
enum EnumC { VALUE_C1  VALUE_C2  VALUE_C3 }

type Query {
  getTypes: CommonInterface
}
```

Consider a query like:

```graphql
query GetAllTypesWithConflictingField {
  getTypes {
    id # ✅ on CommonInterface — no conflict
    ... on TypeA { field }    # field: EnumA
    ... on TypeB { userAlias1: field }  # field: EnumB — user-provided alias
    ... on TypeC { userAlias2: field }  # field: EnumC — user-provided alias
  }
}
```
The Rust Planner Generates:
```graphql
QueryPlan {
          Fetch(service: "service") {
            {
              getTypes {
                id
                __typename
                ... on TypeA {
                  field
                }
                ... on TypeB {
                  _internal_qp_alias_0: field
                }
                ... on TypeC {
                  _internal_qp_alias_0: field
                }
                ... on TypeD {
                  _internal_qp_alias_0: field
                }
              }
            }
          },
        },
```

The problem here is that this is invalid GraphQL syntax and causes the
subgraph query to be malformed. Resulting in a response from the
subgraph like below:
```graphql
 GraphQLError: Fields "_internal_qp_alias_0" conflict because they return conflicting types "EnumB" and "EnumC". Use different aliases on the fields to fetch both if this was intentional.
```
---
### Explanation: Why `SafeSelectionSetMerger` Causes Identical Alias
Names:

The problem is about scope and state persistence of the merger's
internal counter.
``` rust
for (root_def_name, mismatch_path) in mismatches_paths {
    let mut merger = SafeSelectionSetMerger::default();  // Line 61: RESET EACH ITERATION
    // ...
    let next_alias = merger.safe_next_alias_name(&selection_set.items);
}
```
A new `SafeSelectionSetMerger` is created for each mismatch in the list,
which means its aliases_counter (initialized to 0) resets every
iteration.

When processing multiple mismatches across fragments:
1. Mismatch # 1 → merger starts at counter 0 → generates
_internal_qp_alias_0
2. Mismatch # 2 → NEW merger starts at counter 0 → generates
_internal_qp_alias_0 (COLLISION!)
3. Mismatch # 3 → NEW merger starts at counter 0 → generates
_internal_qp_alias_0 (COLLISION!)
---

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
This patch includes the fixes in the query planner including the fixes
for mismatch handling so conflicting fields are tracked by response key
(alias-aware), and internal alias rewrites restore the original
client-facing key (alias-or-name) instead of always the schema field
name.
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
> [!IMPORTANT]
> Merging this pull request will create these releases

# node-addon 0.0.17 (2026-04-01)
## Fixes

- This patch includes the fixes in the query planner including the fixes
for mismatch handling so conflicting fields are tracked by response key
(alias-aware), and internal alias rewrites restore the original
client-facing key (alias-or-name) instead of always the schema field
name.

Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
ardatan and others added 28 commits May 5, 2026 14:39
Ref ROUTER-100
Ref ROUTER-118
Closes #340

Documentation graphql-hive/docs#94

# TLS Support

Adds TLS support to Hive Router for both client and subgraph
connections, including mutual TLS (mTLS) authentication. This allows
secure communication between clients, the router, and subgraphs by
encrypting data in transit and optionally verifying identities.

## TLS Directions

TLS Support has implementations for the following 4 directions:

### Router -> Client - Regular TLS
Router has an `identity` (`cert`, `key`), and client has `cert`, then
Client validates the router's `identity`

### Client -> Router - mTLS
Router has the `cert`, client has the `identity`, mTLS/Client Auth then
the router validates the client's `identity`

### Subgraph -> Router - Regular TLS
Subgraph has the `identity` (`cert`, `key`), and router has `cert`, then
Router validates the subgraph's `identity`.

### Router -> Subgraph - mTLS
Subgraph has the `cert`, router(which is the client this time) has the
`identity`, then subgraph validates the router's `identity`.

## TLS Directions Diagram

```mermaid
flowchart LR
    Client["Client"]
    Router["Router"]
    Subgraph["Subgraph"]

    %% Router -> Client: Regular TLS
    Router -- "TLS\n(cert_file + key_file)" --> Client
    Client -. "validates router identity\n(cert_file)" .-> Router

    %% Client -> Router: mTLS / Client Auth
    Client -- "mTLS\n(client identity)" --> Router
    Router -. "validates client identity\n(client_auth.cert_file)" .-> Client

    %% Subgraph -> Router: Regular TLS
    Subgraph -- "TLS\n(cert_file)" --> Router
    Router -. "validates subgraph identity\n(all/subgraphs.cert_file)" .-> Subgraph

    %% Router -> Subgraph: mTLS
    Router -- "mTLS\n(client_auth.cert_file + key_file)" --> Subgraph
    Subgraph -. "validates router identity\n(cert_file)" .-> Router
```

## Configuration Structure
```yaml
traffic_shaping:
  router:
    key_file:          # Router server private key
    cert_file:         # Router server certificate(s)
    client_auth:       # mTLS: Client -> Router
       cert_file:      # Trusted client CA certificate(s)
  all:                 # Default TLS for all subgraph connections
    cert_file:         # Trusted subgraph CA certificate(s)
    client_auth:       # mTLS: Router -> Subgraph
       cert_file:      # Router client certificate(s)
       key_file:       # Router client private key
  subgraphs:
    SUBGRAPH_NAME:     # Per-subgraph TLS override
      cert_file:       # Trusted subgraph CA certificate(s)
      client_auth:     # mTLS: Router -> Subgraph
         cert_file:    # Router client certificate(s)
         key_file:     # Router client private key
```

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: theguild-bot <bot@the-guild.dev>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Closes #340
Ref ROUTER-118

- Add E2E tests HTTP/2 support for Subgraphs <-> Router and Router <->
Client
- Implement `http2_only` flag to enable H2C for Subgraphs <-> Router

---------

Co-authored-by: theguild-bot <bot@the-guild.dev>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…#942)

Bumps the cargo group with 1 update in the / directory:
[rustls-webpki](https://github.com/rustls/webpki).
Bumps the cargo group with 2 updates in the /apollo-router-workspace
directory: [rustls-webpki](https://github.com/rustls/webpki) and
[thin-vec](https://github.com/mozilla/thin-vec).

Updates `rustls-webpki` from 0.103.12 to 0.103.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rustls/webpki/releases">rustls-webpki's
releases</a>.</em></p>
<blockquote>
<h2>0.103.13</h2>
<ul>
<li><strong>Fix reachable panic in parsing a CRL</strong>. This was
reported to us as <a
href="https://github.com/rustls/webpki/security/advisories/GHSA-82j2-j2ch-gfr8">GHSA-82j2-j2ch-gfr8</a>.
Users who don't use CRLs are not affected.</li>
<li>For name constraints on URI names, we incorrectly processed excluded
subtrees in a way which inverted the desired meaning. See <a
href="https://redirect.github.com/rustls/webpki/pull/471">rustls/webpki#471</a>.
This was a case missing in the fix for <a
href="https://github.com/advisories/GHSA-965h-392x-2mh5">https://github.com/advisories/GHSA-965h-392x-2mh5</a>.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Actually fail closed for URI matching against excluded subtrees by
<a href="https://github.com/djc"><code>@​djc</code></a> in <a
href="https://redirect.github.com/rustls/webpki/pull/473">rustls/webpki#473</a></li>
<li>Prepare 0.103.13 by <a
href="https://github.com/ctz"><code>@​ctz</code></a> in <a
href="https://redirect.github.com/rustls/webpki/pull/474">rustls/webpki#474</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13">https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rustls/webpki/commit/2879b2ce7a476181ac3050f73fe0835f04728e86"><code>2879b2c</code></a>
Prepare 0.103.13</li>
<li><a
href="https://github.com/rustls/webpki/commit/2c49773d823f48c87db30db7a66c25993c847007"><code>2c49773</code></a>
Improve tests for padding of <code>BitStringFlags</code></li>
<li><a
href="https://github.com/rustls/webpki/commit/4e3c0b393a7bfb9cbe6dcdc8309cbadf8ee00c51"><code>4e3c0b3</code></a>
Correct validation of BIT STRING constraints</li>
<li><a
href="https://github.com/rustls/webpki/commit/39c91d2525a542a7f651a1a62c3462e8115cc39e"><code>39c91d2</code></a>
Actually fail closed for URI matching against excluded subtrees</li>
<li>See full diff in <a
href="https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `rustls-webpki` from 0.103.12 to 0.103.13
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/rustls/webpki/releases">rustls-webpki's
releases</a>.</em></p>
<blockquote>
<h2>0.103.13</h2>
<ul>
<li><strong>Fix reachable panic in parsing a CRL</strong>. This was
reported to us as <a
href="https://github.com/rustls/webpki/security/advisories/GHSA-82j2-j2ch-gfr8">GHSA-82j2-j2ch-gfr8</a>.
Users who don't use CRLs are not affected.</li>
<li>For name constraints on URI names, we incorrectly processed excluded
subtrees in a way which inverted the desired meaning. See <a
href="https://redirect.github.com/rustls/webpki/pull/471">rustls/webpki#471</a>.
This was a case missing in the fix for <a
href="https://github.com/advisories/GHSA-965h-392x-2mh5">https://github.com/advisories/GHSA-965h-392x-2mh5</a>.</li>
</ul>
<h2>What's Changed</h2>
<ul>
<li>Actually fail closed for URI matching against excluded subtrees by
<a href="https://github.com/djc"><code>@​djc</code></a> in <a
href="https://redirect.github.com/rustls/webpki/pull/473">rustls/webpki#473</a></li>
<li>Prepare 0.103.13 by <a
href="https://github.com/ctz"><code>@​ctz</code></a> in <a
href="https://redirect.github.com/rustls/webpki/pull/474">rustls/webpki#474</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13">https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/rustls/webpki/commit/2879b2ce7a476181ac3050f73fe0835f04728e86"><code>2879b2c</code></a>
Prepare 0.103.13</li>
<li><a
href="https://github.com/rustls/webpki/commit/2c49773d823f48c87db30db7a66c25993c847007"><code>2c49773</code></a>
Improve tests for padding of <code>BitStringFlags</code></li>
<li><a
href="https://github.com/rustls/webpki/commit/4e3c0b393a7bfb9cbe6dcdc8309cbadf8ee00c51"><code>4e3c0b3</code></a>
Correct validation of BIT STRING constraints</li>
<li><a
href="https://github.com/rustls/webpki/commit/39c91d2525a542a7f651a1a62c3462e8115cc39e"><code>39c91d2</code></a>
Actually fail closed for URI matching against excluded subtrees</li>
<li>See full diff in <a
href="https://github.com/rustls/webpki/compare/v/0.103.12...v/0.103.13">compare
view</a></li>
</ul>
</details>
<br />

Updates `thin-vec` from 0.2.14 to 0.2.16
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/mozilla/thin-vec/blob/main/RELEASES.md">thin-vec's
changelog</a>.</em></p>
<blockquote>
<h1>Version 0.2.16 (2026-04-14)</h1>
<ul>
<li>Fix reserve() on auto arrays in gecko-ffi mode.</li>
<li>Fix two double-drop issues with ThinVec::clear() and
ThinVec::into_iter()
when the Drop implementation of the item panics.</li>
</ul>
<h1>Version 0.2.15 (2026-04-08)</h1>
<ul>
<li>Support AutoTArrays created from Rust in Gecko FFI mode.</li>
<li>Add extract_if.</li>
<li>Add const new() support behind feature flag.</li>
<li>Fix <code>thin_vec</code> macro not being hygienic when
recursing</li>
<li>Improve extend() performance.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/mozilla/thin-vec/commit/3c96f1e335e695e6f6d43a3d383a9ea9f1f9d586"><code>3c96f1e</code></a>
chore: Bump version to v0.2.16</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/df64748355222525c344ecd9d2c9f59a662e1678"><code>df64748</code></a>
Fix two panic=unwind issues.</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/4e3a217b7fb27e1e8dc08a7307b831f9928e21a5"><code>4e3a217</code></a>
ci: Ignore msrv job for now since it just hangs trying to pull
deps.</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/63c2f5fcf2a5d84f23ed45bbbd053fe1bd2cc96f"><code>63c2f5f</code></a>
gecko-ffi: Fix auto-t-array push.</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/679781320925000f5dfe34fdea9c440ade34561a"><code>6797813</code></a>
tests: Appease clippy.</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/af81b17ad58c806af61c2a85e1cc53242a10d2e0"><code>af81b17</code></a>
ci: Don't use actions-rs/{cargo,clippy-check} as it's not allowed in
mozilla/...</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/360f9ef0c91a1068c0acbd5a0fd206911dec5ef3"><code>360f9ef</code></a>
Update repository URL and various cleanups</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/70bcca0960a7e11056fa3281445d08052421dab5"><code>70bcca0</code></a>
chore: Bump version to v0.2.15</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/322423b7a6951346e76fcdaa20ee01a91033e180"><code>322423b</code></a>
Fix miri error on extract_if().</li>
<li><a
href="https://github.com/mozilla/thin-vec/commit/eca5334c291cc65885bf524f61e5fe4a679a4152"><code>eca5334</code></a>
Don't make push_unchecked public.</li>
<li>Additional commits viewable in <a
href="https://github.com/mozilla/thin-vec/compare/v0.2.14...v0.2.16">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/graphql-hive/router/network/alerts).

</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…2 updates (#945)

Bumps the npm_and_yarn group with 2 updates in the / directory:
[axios](https://github.com/axios/axios) and
[follow-redirects](https://github.com/follow-redirects/follow-redirects).

Updates `axios` from 1.14.0 to 1.15.2
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/releases">axios's
releases</a>.</em></p>
<blockquote>
<h2>v1.15.2</h2>
<p>This release delivers prototype-pollution hardening for the Node HTTP
adapter, adds an opt-in <code>allowedSocketPaths</code> allowlist to
mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory
leak, and ships supply-chain hardening across CI and security docs.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Prototype Pollution Hardening (HTTP Adapter):</strong>
Hardened the Node HTTP adapter and
<code>resolveConfig</code>/<code>mergeConfig</code>/validator paths to
read only own properties and use null-prototype config objects,
preventing polluted <code>auth</code>, <code>baseURL</code>,
<code>socketPath</code>, <code>beforeRedirect</code>, and
<code>insecureHTTPParser</code> from influencing requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a></strong>)</li>
<li><strong>SSRF via <code>socketPath</code>:</strong> Rejects
non-string <code>socketPath</code> values and adds an opt-in
<code>allowedSocketPaths</code> config option to restrict permitted Unix
domain socket paths, returning <code>AxiosError</code>
<code>ERR_BAD_OPTION_VALUE</code> on mismatch. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
<li><strong>Supply-chain Hardening:</strong> Added <code>.npmrc</code>
with <code>ignore-scripts=true</code>, lockfile lint CI, non-blocking
reproducible build diff, scoped CODEOWNERS, expanded
<code>SECURITY.md</code>/<code>THREATMODEL.md</code> with provenance
verification (<code>npm audit signatures</code>), 60-day resolution
policy, and maintainer incident-response runbook. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong><code>allowedSocketPaths</code> Config Option:</strong> New
request config option (and TypeScript types) to allowlist Unix domain
socket paths used by the Node http adapter; backwards compatible when
unset. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Keep-alive Socket Memory Leak:</strong> Installs a single
per-socket <code>error</code> listener tracking the active request via
<code>kAxiosSocketListener</code>/<code>kAxiosCurrentReq</code>,
eliminating per-request listener accumulation,
<code>MaxListenersExceededWarning</code>, and linear heap growth under
concurrent or long-running keep-alive workloads (fixes <a
href="https://redirect.github.com/axios/axios/issues/10780">#10780</a>).
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li><strong>Changelog:</strong> Updated <code>CHANGELOG.md</code> with
v1.15.1 release notes. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.15.1...v1.15.2">Full
Changelog</a></p>
<h2>v1.15.1</h2>
<p>This release ships a coordinated set of security hardening fixes
across headers, body/redirect limits, multipart handling, and
XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes,
test migrations, and threat-model documentation updates.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Header Injection Hardening:</strong> Tightened validation
and sanitisation across request header construction to close the
header-injection attack surface. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10749">#10749</a></strong>)</li>
<li><strong>CRLF Stripping in Multipart Headers:</strong> Correctly
strips CR/LF from multipart header values to prevent injection via field
names and filenames. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10758">#10758</a></strong>)</li>
<li><strong>Prototype Pollution / Auth Bypass:</strong> Replaced unsafe
<code>in</code> checks with <code>hasOwnProperty</code> to prevent
authentication bypass via prototype pollution on config objects, with
additional regression tests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10761">#10761</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10760">#10760</a></strong>)</li>
<li><strong><code>withXSRFToken</code> Truthy Bypass:</strong>
Short-circuits on any truthy non-boolean value, so an ambiguous config
no longer silently leaks the XSRF token cross-origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a></strong>)</li>
<li><strong><code>maxBodyLength</code> With Zero Redirects:</strong>
Enforces <code>maxBodyLength</code> even when <code>maxRedirects</code>
is set to <code>0</code>, closing a bypass path for oversized request
bodies. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10753">#10753</a></strong>)</li>
<li><strong>Streamed Response <code>maxContentLength</code>
Bypass:</strong> Applies <code>maxContentLength</code> to streamed
responses that previously bypassed the cap. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10754">#10754</a></strong>)</li>
<li><strong>Follow-up CVE Completion:</strong> Completes an earlier
incomplete CVE fix to fully close the regression window. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10755">#10755</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>AI-Based Docs Translations:</strong> Initial scaffold for
AI-assisted translations of the documentation site. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10705">#10705</a></strong>)</li>
<li><strong><code>Location</code> Request Header Type:</strong> Adds
<code>Location</code> to <code>CommonRequestHeadersList</code> for
accurate typing of redirect-aware requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7528">#7528</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>FormData Handling:</strong> Removes
<code>Content-Type</code> when no boundary is present on
<code>FormData</code> fetch requests, supports multi-select fields,
cancels <code>request.body</code> instead of the source stream on fetch
abort, and fixes a recursion bug in form-data serialisation. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7314">#7314</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10676">#10676</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10702">#10702</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10726">#10726</a></strong>)</li>
<li><strong>HTTP Adapter:</strong> Handles socket-only request errors
without leaking keep-alive listeners. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10576">#10576</a></strong>)</li>
<li><strong>Progress Events:</strong> Clamps <code>loaded</code> to
<code>total</code> for computable upload/download progress events.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/7458">#7458</a></strong>)</li>
<li><strong>Types:</strong> Aligns <code>runWhen</code> type with the
runtime behaviour in <code>InterceptorManager</code> and makes response
header keys case-insensitive. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7529">#7529</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10677">#10677</a></strong>)</li>
<li><strong><code>buildFullPath</code>:</strong> Uses strict equality in
the base/relative URL check. (<strong><a
href="https://redirect.github.com/axios/axios/issues/7252">#7252</a></strong>)</li>
<li><strong><code>AxiosURLSearchParams</code> Regex:</strong> Improves
the regex used for param serialisation to avoid edge-case mismatches.
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10736">#10736</a></strong>)</li>
<li><strong>Resilient Value Parsing:</strong> Parses out header/config
values instead of throwing on malformed input. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10687">#10687</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/axios/axios/blob/v1.x/CHANGELOG.md">axios's
changelog</a>.</em></p>
<blockquote>
<h2>v1.15.2 - April 21, 2026</h2>
<p>This release delivers prototype-pollution hardening for the Node HTTP
adapter, adds an opt-in <code>allowedSocketPaths</code> allowlist to
mitigate SSRF via Unix domain sockets, fixes a keep-alive socket memory
leak, and ships supply-chain hardening across CI and security docs.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li><strong>Prototype Pollution Hardening (HTTP Adapter):</strong>
Hardened the Node HTTP adapter and
<code>resolveConfig</code>/<code>mergeConfig</code>/validator paths to
read only own properties and use null-prototype config objects,
preventing polluted <code>auth</code>, <code>baseURL</code>,
<code>socketPath</code>, <code>beforeRedirect</code>, and
<code>insecureHTTPParser</code> from influencing requests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a></strong>)</li>
<li><strong>SSRF via <code>socketPath</code>:</strong> Rejects
non-string <code>socketPath</code> values and adds an opt-in
<code>allowedSocketPaths</code> config option to restrict permitted Unix
domain socket paths, returning <code>AxiosError</code>
<code>ERR_BAD_OPTION_VALUE</code> on mismatch. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
<li><strong>Supply-chain Hardening:</strong> Added <code>.npmrc</code>
with <code>ignore-scripts=true</code>, lockfile lint CI, non-blocking
reproducible build diff, scoped CODEOWNERS, expanded
<code>SECURITY.md</code>/<code>THREATMODEL.md</code> with provenance
verification (<code>npm audit signatures</code>), 60-day resolution
policy, and maintainer incident-response runbook. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a></strong>)</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong><code>allowedSocketPaths</code> Config Option:</strong> New
request config option (and TypeScript types) to allowlist Unix domain
socket paths used by the Node http adapter; backwards compatible when
unset. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a></strong>)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li><strong>Keep-alive Socket Memory Leak:</strong> Installs a single
per-socket <code>error</code> listener tracking the active request via
<code>kAxiosSocketListener</code>/<code>kAxiosCurrentReq</code>,
eliminating per-request listener accumulation,
<code>MaxListenersExceededWarning</code>, and linear heap growth under
concurrent or long-running keep-alive workloads (fixes <a
href="https://redirect.github.com/axios/axios/issues/10780">#10780</a>).
(<strong><a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a></strong>)</li>
</ul>
<h2>🔧 Maintenance &amp; Chores</h2>
<ul>
<li><strong>Changelog:</strong> Updated <code>CHANGELOG.md</code> with
v1.15.1 release notes. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a></strong>)</li>
</ul>
<p><a
href="https://github.com/axios/axios/compare/v1.15.1...v1.15.2">Full
Changelog</a></p>
<hr />
<h2>v1.15.1 - April 19, 2026</h2>
<p>This release ships a coordinated set of security hardening fixes
across headers, body/redirect limits, multipart handling, and
XSRF/prototype-pollution vectors, alongside a broad sweep of bug fixes,
test migrations, and threat-model documentation updates.</p>
<h2>🔒 Security Fixes</h2>
<ul>
<li>
<p><strong>Header Injection Hardening:</strong> Tightened validation and
sanitisation across request header construction to close the
header-injection attack surface. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10749">#10749</a></strong>)</p>
</li>
<li>
<p><strong>CRLF Stripping in Multipart Headers:</strong> Correctly
strips CR/LF from multipart header values to prevent injection via field
names and filenames. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10758">#10758</a></strong>)</p>
</li>
<li>
<p><strong>Prototype Pollution / Auth Bypass:</strong> Replaced unsafe
<code>in</code> checks with <code>hasOwnProperty</code> to prevent
authentication bypass via prototype pollution on config objects, with
additional regression tests. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10761">#10761</a></strong>,
<strong><a
href="https://redirect.github.com/axios/axios/issues/10760">#10760</a></strong>)</p>
</li>
<li>
<p><strong><code>withXSRFToken</code> Truthy Bypass:</strong>
Short-circuits on any truthy non-boolean value, so an ambiguous config
no longer silently leaks the XSRF token cross-origin. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a></strong>)</p>
</li>
<li>
<p><strong><code>maxBodyLength</code> With Zero Redirects:</strong>
Enforces <code>maxBodyLength</code> even when <code>maxRedirects</code>
is set to <code>0</code>, closing a bypass path for oversized request
bodies. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10753">#10753</a></strong>)</p>
</li>
<li>
<p><strong>Streamed Response <code>maxContentLength</code>
Bypass:</strong> Applies <code>maxContentLength</code> to streamed
responses that previously bypassed the cap. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10754">#10754</a></strong>)</p>
</li>
<li>
<p><strong>Follow-up CVE Completion:</strong> Completes an earlier
incomplete CVE fix to fully close the regression window. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10755">#10755</a></strong>)</p>
</li>
</ul>
<h2>🚀 New Features</h2>
<ul>
<li><strong>AI-Based Docs Translations:</strong> Initial scaffold for
AI-assisted translations of the documentation site. (<strong><a
href="https://redirect.github.com/axios/axios/issues/10705">#10705</a></strong>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/axios/axios/commit/582934382e4e0e0bcb679c628071a4203e93cf57"><code>5829343</code></a>
chore(release): prepare release 1.15.2 (<a
href="https://redirect.github.com/axios/axios/issues/10789">#10789</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/4709a48fa2717ba97f43f5432d48ca4e26c2d326"><code>4709a48</code></a>
fix: added fix for memory leak in sockets (<a
href="https://redirect.github.com/axios/axios/issues/10788">#10788</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/be3336014e01f9a4fc1f8aef15303cf7daaf58db"><code>be33360</code></a>
chore: update changelog (<a
href="https://redirect.github.com/axios/axios/issues/10781">#10781</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/47915144662f2733e6c051bdcb895a8c8f0586aa"><code>4791514</code></a>
fix: more header pollutions (<a
href="https://redirect.github.com/axios/axios/issues/10779">#10779</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/6feafcff6c2dbafe206161c5d09e38e1d36af66f"><code>6feafcf</code></a>
fix: socket issue (<a
href="https://redirect.github.com/axios/axios/issues/10777">#10777</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/302e2739c602f00e323d4f3f5c79500647633a73"><code>302e273</code></a>
docs: update docs, add a couple actions etc (<a
href="https://redirect.github.com/axios/axios/issues/10776">#10776</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/ac42446be51300fe214ba3c6e40cc95f34fd6871"><code>ac42446</code></a>
chore(release): prepare release 1.15.1 (<a
href="https://redirect.github.com/axios/axios/issues/10767">#10767</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/908f2206b6bfeff67236784abce85935698ac1d9"><code>908f220</code></a>
docs: update threatmodel (<a
href="https://redirect.github.com/axios/axios/issues/10765">#10765</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/f93f8155250c2e066205521eda05ae22983a1f6d"><code>f93f815</code></a>
docs: added docs around potential decompressions bomb (<a
href="https://redirect.github.com/axios/axios/issues/10763">#10763</a>)</li>
<li><a
href="https://github.com/axios/axios/commit/1728aa1b15b8857f970611fd8983c06b423fc486"><code>1728aa1</code></a>
fix: short-circuits on any truthy non-boolean in withXSRFToken (<a
href="https://redirect.github.com/axios/axios/issues/10762">#10762</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/axios/axios/compare/v1.14.0...v1.15.2">compare
view</a></li>
</ul>
</details>
<br />

Updates `follow-redirects` from 1.15.11 to 1.16.0
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/follow-redirects/follow-redirects/commit/0c23a223067201c368035e82954c11eb2578a33b"><code>0c23a22</code></a>
Release version 1.16.0 of the npm package.</li>
<li><a
href="https://github.com/follow-redirects/follow-redirects/commit/844c4d302ac963d29bdb5dc1754ec7df3d70d7f9"><code>844c4d3</code></a>
Add sensitiveHeaders option.</li>
<li><a
href="https://github.com/follow-redirects/follow-redirects/commit/5e8b8d024e2c76f804a284258e585ecb49a575be"><code>5e8b8d0</code></a>
ci: add Node.js 24.x to the CI matrix</li>
<li><a
href="https://github.com/follow-redirects/follow-redirects/commit/7953e2255aa0b93602eed3804f3bc5e6923a03af"><code>7953e22</code></a>
ci: upgrade GitHub Actions to use setup-node@v6 and checkout@v6</li>
<li><a
href="https://github.com/follow-redirects/follow-redirects/commit/86dc1f86e4b56bcd642c78384d51f10f123aea75"><code>86dc1f8</code></a>
Sanitizing input.</li>
<li>See full diff in <a
href="https://github.com/follow-redirects/follow-redirects/compare/v1.15.11...v1.16.0">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/graphql-hive/router/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: knope-bot[bot] <152252888+knope-bot[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
How to install:
https://nexte.st/docs/installation/pre-built-binaries/

Closes #819

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: Dotan Simha <dotan@the-guild.dev>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
#951)

Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
The `http.server` span now includes:
- `client.address` and `client.port` from a configurable request header
- `network.peer.address` and `network.peer.port` from the address of the
incoming connection

```yaml
telemetry:
  client_identification:
    # Default - use socket peer only
    ip_header: null
    
    # Header name - use the left-most valid IP from the header
    ip_header: x-forwarded-for
    
    # Trusted proxies - only trust the header when the socket peer is trusted
    ip_header:
      name: x-forwarded-for
      trusted_proxies:
        - 10.0.0.0/8
        - 192.168.0.0/16
```

In trusted proxies scenario, the Router scans the configured header from
right to left, skips trusted proxy IP ranges, and records the first
non-trusted IP as `client.address`.
If no valid client IP can be resolved, the Router falls back to the
socket peer address.
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Removes `bollard` dependency and e2e Docker test helper. Implements an
in-process redis server for `response_cache` plugin tests and switch
tests to inline config.

---

We have a test failure from time to time and we rely on Docker yada
yada, so I created a tiny redis server for mocking as we really only use
it for a single plugin test.
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…953)

Continue #948 here (as I have no push rights there) and fix issues with
the merging logic.

Closes: #949 and #948

---------

Co-authored-by: hgonz20 <heriberto.gonzalez@aexp.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
#882)

The benchmark suite now uses `wrk` for lower-overhead HTTP load testing
while preserving response validation. This keeps throughput measurements
focused on router performance and still fails the benchmark when
responses have invalid status codes, GraphQL errors, or unexpected
response bodies.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…fragment being dropped (#946)

- [x] Run `cargo clippy --fix` to auto-fix lint issues
- [x] Run `cargo fmt` to fix formatting issues
- [x] Add node-addon to changeset
- [x] Fix directive semantics: propagate parent fragment directives into
specific sub-fragments (only adding directives not already present)
instead of wrapping in an outer fragment — avoids redundant nesting when
sub-fragment already carries the same condition as the parent
- [x] Fix regression test to actually exercise
`expand_abstract_fragment` using a concrete parent type (`account(id:)`)
with an abstract type fragment (`... on Node`)
- [x] Update insta snapshots for the updated test and the affected
normalization snapshot

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ardatan <20847995+ardatan@users.noreply.github.com>
Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: Arda TANRIKULU <ardatanrikulu@gmail.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Implements Coprocessor feature to allow external service to intercept
and modify GraphQL requests/responses at different stages of the request
pipeline.

Design doc: https://guild-oss.slack.com/docs/TAYJ1FSUA/F0ASCC492KS


- [x] context #937
- [x] public schema sdl
- [ ] execution stage (future - when demand)
- [ ] subgraph stage (future - when demand)
- [ ] tls (for http/2) (future - when demand)
- [ ] different endpoints per stage (future - when demand)
- [x] benchmark (~11k drops to ~9.2k rps)

---

This PR introduces Coprocessor API. The goal is to let users extend
Router in language agnostic way.

## Building blocks
- `Stage` trait that represents a step in the request's pipeline. Every
`Stage` implementation defines how to build the http request to
coprocessor service, how to parse the response and how to apply
mutations. Every stage can `"continue"` or `"break": <status_code>` the
flow early.
- `CoprocessorRuntime` wires these stages into one API that is called by
Hive Router.
- `RequestContext` - introduced in #937

Every stage has configurable `include` object, so users can opt into the
pieces of data they need.
The `include`'s set of fields is different for every stage.

```yaml
include:
  body: true
  headers: true
```

The `context` (that represents `RequestContext`) in all of stages allows
users to select what should be passed to the coprocessor service.

```yaml
include:
  context: true # all
  context: ["hive::operation::name"] # only operation's name
```

Currently, we support those stages (they run in this order):
- `router.request`
- `graphql.request`
- `graphql.analysis`
- `graphql.response`
- `router.response`

Those stages are covered in the [design
doc](https://guild-oss.slack.com/docs/TAYJ1FSUA/F0ASCC492KS).

The design is forward‑compatible, adding new stages (like execution or
subgraph stages) can be added later by implementing the Stage trait.

## Coprocessor service

A coprocessor service can be accessed over http or unix domain socket
with http/1, http/2 or h2c protocol.
When using UDS with Router, it's in user's hand to create or truncate
the socket file. Hive Router only "talks" to it.

## Observability

I covered metrics, spans and logs around coprocessor runtime.

Metrics:
- `hive.router.coprocessor.requests_total{"coprocessor.stage"}` - Total
number of coprocessor requests
- `hive.router.coprocessor.duration{"coprocessor.stage"}` - Duration of
coprocessor requests
- `hive.router.coprocessor.errors_total{"coprocessor.stage"}` - Total
number of coprocessor errors
- http/uds client of coprocessor api, supports also the `http.client`
metrics so users will know about http status codes, responses etc.

Spans:
- `coprocessor` span with `coprocessor.stage` and `coprocessor.id`
attributes wraps all stage calls
- `http.client` span wraps http requests to coprocessor service

Logs:
- Every coprocessor response, error, request action has corresponding
log line (usually with `debug` level, except `error` for errors) with
attributes allowing to correlate coprocessor logs with http logs and
graphql logs. There's a link :)
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
GHSA-w5hq-g745-h8pq

The `uuid` library is used by `@graphql-hive/laboratory` so it's part of
Hive Router, but UUIDs are never user-controlled.
The second instance of `uuid` is inside fed audit's dependencies within
the apollo/* libs, that are not user-controlled and also a dev
dependency so it has zero impact.

Closes #950
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
…e spread directives (#956)

Closes #939

Fixes query normalization for fragment spreads and preserves `@include`
and `@skip` directives on fragment spreads.

---------

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Ref ROUTER-282

---------

Co-authored-by: Kamil Kisiela <kamil.kisiela@gmail.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Co-authored-by: kamilkisiela <8167190+kamilkisiela@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 5, 2026

@copilot rebase

Rebased. Branch is now up to date and pushed at d69f110.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants