[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-apollo-graphql-apollo-router":3,"mdc-w63pwq-key":37,"related-repo-apollo-graphql-apollo-router":2927,"related-org-apollo-graphql-apollo-router":3027},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":32,"sourceUrl":35,"mdContent":36},"apollo-router","configure Apollo Router for GraphQL federation","Version-aware guide for configuring and running Apollo Router for federated GraphQL supergraphs. Generates correct YAML for both Router v1.x and v2.x. Use this skill when: (1) setting up Apollo Router to run a supergraph, (2) configuring routing, headers, or CORS, (3) implementing custom plugins (Rhai scripts or coprocessors), (4) configuring telemetry (tracing, metrics, logging), (5) troubleshooting Router performance or connectivity issues, (6) securing the graph with JWT, declarative field-level authorization directives, or persisted-query safelisting, (7) managing router.yaml as version-controlled config with CI\u002FCD validation.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"apollo-graphql","Apollo GraphQL","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fapollo-graphql.png","apollographql",[13,17,20,21],{"name":14,"slug":15,"type":16},"GraphQL","graphql","tag",{"name":18,"slug":19,"type":16},"Architecture","architecture",{"name":9,"slug":8,"type":16},{"name":22,"slug":23,"type":16},"Deployment","deployment",97,"https:\u002F\u002Fgithub.com\u002Fapollographql\u002Fskills","2026-07-30T05:31:54.665938","MIT",11,[30,31,15],"agent-skills","apollo",{"repoUrl":25,"stars":24,"forks":28,"topics":33,"description":34},[30,31,15],"Apollo GraphQL Agent Skills","https:\u002F\u002Fgithub.com\u002Fapollographql\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fapollo-router","---\nname: apollo-router\ndescription: >\n  Version-aware guide for configuring and running Apollo Router for federated GraphQL supergraphs.\n  Generates correct YAML for both Router v1.x and v2.x. Use this skill when:\n  (1) setting up Apollo Router to run a supergraph,\n  (2) configuring routing, headers, or CORS,\n  (3) implementing custom plugins (Rhai scripts or coprocessors),\n  (4) configuring telemetry (tracing, metrics, logging),\n  (5) troubleshooting Router performance or connectivity issues,\n  (6) securing the graph with JWT, declarative field-level authorization directives, or persisted-query safelisting,\n  (7) managing router.yaml as version-controlled config with CI\u002FCD validation.\nlicense: MIT\ncompatibility: Linux\u002FmacOS\u002FWindows. Requires a composed supergraph schema from Rover or GraphOS.\nmetadata:\n  author: apollographql\n  version: \"2.5.0\"\nallowed-tools: Bash(router:*) Bash(.\u002Frouter:*) Bash(rover:*) Bash(curl:*) Bash(docker:*) Read Write Edit Glob Grep\n---\n\n# Apollo Router Config Generator\n\nApollo Router is a high-performance graph router written in Rust for running Apollo Federation 2 supergraphs. It sits in front of your subgraphs and handles query planning, execution, and response composition.\n\n**This skill generates version-correct configuration.** Router v1 and v2 have incompatible config schemas in several critical sections (CORS, JWT auth, connectors). Always determine the target version before generating any config.\n\n## Step 1: Version Selection\n\nAsk the user **before generating any config**:\n\n```\nWhich Apollo Router version are you targeting?\n\n  [1] Router v2.x (recommended — current LTS, required for Connectors)\n  [2] Router v1.x (legacy — end-of-support announced, security patches only)\n  [3] Not sure — help me decide\n```\n\nIf the user picks **[3]**, display:\n\n```\nQuick guide:\n\n  • Pick v2 if: you're starting fresh, using Apollo Connectors for REST APIs,\n    or want backpressure-based overload protection.\n  • Pick v1 if: you have an existing deployment and haven't migrated yet.\n    Note: Apollo ended active support for v1.x. The v2.10 LTS (Dec 2025)\n    is the current baseline. Migration is strongly recommended.\n\n  Tip: If you have an existing router.yaml, you can auto-migrate it:\n    router config upgrade router.yaml\n```\n\nStore the selection as `ROUTER_VERSION=v1|v2` to gate all subsequent template generation.\n\n## Step 2: Environment Selection\n\nAsk: **Production** or **Development**?\n\n- **Production**: security-hardened defaults (introspection off, sandbox off, homepage off, subgraph errors hidden, auth required, health check on)\n- **Development**: open defaults (introspection on, sandbox on, errors exposed, text logging)\n\nLoad the appropriate base template from:\n- `templates\u002F{version}\u002Fproduction.yaml`\n- `templates\u002F{version}\u002Fdevelopment.yaml`\n\n## Step 3: Feature Selection\n\nAsk which features to include:\n\n- [ ] JWT Authentication\n- [ ] Declarative Authorization (field-level `@authenticated` \u002F `@requiresScopes` \u002F `@policy` directives — requires GraphOS + request claims)\n- [ ] CORS (almost always yes for browser clients)\n- [ ] Operation Limits\n- [ ] Traffic Shaping \u002F Rate Limiting\n- [ ] Telemetry (Prometheus, OTLP tracing, JSON logging)\n- [ ] APQ (Automatic Persisted Queries — performance\u002Fbandwidth only, NOT a security control)\n- [ ] Persisted Query Safelisting (GraphOS PQL operation allowlist — a security control; distinct from APQ)\n- [ ] Connectors (REST API integration — Router v2 only; GA key is `connectors`, early v2 preview key was `preview_connectors`)\n- [ ] Subscriptions\n- [ ] Header Propagation\n- [ ] Response Caching (entity + root field caching with Redis — Router v2 only, v2.6.0+)\n\n## Step 4: Gather Parameters\n\nFor each selected feature, collect required values.\n\n- Use section templates from `templates\u002F{version}\u002Fsections\u002F` for `auth`, `cors`, `headers`, `limits`, `telemetry`, and `traffic-shaping`.\n- For Connectors in v2, use `templates\u002Fv2\u002Fsections\u002Fconnectors.yaml` as the source.\n- For APQ and subscriptions, copy the snippet from the selected base template (`templates\u002F{version}\u002Fproduction.yaml` or `templates\u002F{version}\u002Fdevelopment.yaml`) or from references.\n- Only offer Connectors when `ROUTER_VERSION=v2`.\n\n### CORS\n- List of allowed origins (never use `\"*\"` for production)\n\n### JWT Authentication\n- JWKS URL\n- Issuer(s) — note: v1 uses singular `issuer`, v2 uses plural `issuers` array\n\n### Declarative Authorization (field-level)\n\n> Field- and type-level access control enforced **in the router**, via the `@authenticated`, `@requiresScopes`, and `@policy` directives applied in subgraph schemas. This is the layer that the global `authorization.require_authentication` gate cannot express. It is a **GraphOS feature** (Enterprise; Developer\u002FStandard plans require Router v2.6.0+) and requires a router connected to GraphOS. Directives are **enabled by default** — config only turns them *off*.\n\nConfirm prerequisites before recommending these:\n\n- **Router connected to GraphOS** (Router v1.29.1+; Developer\u002FStandard plans need v2.6.0+).\n- **A claims source.** Directives evaluate the claims at the `apollo::authentication::jwt_claims` context key. Populate it via JWT authentication (configure that feature too) **or** a coprocessor that injects claims.\n- **`@policy` additionally requires a Supergraph plugin** (Rhai script or coprocessor) to evaluate each policy — the router extracts required policies into `apollo::authorization::required_policies` but does not decide them itself.\n\nAsk:\n- **Which fields\u002Ftypes need protection, and at what level?** (`@authenticated` = any valid identity; `@requiresScopes` = specific scopes; `@policy` = custom logic.)\n- **Where do scopes\u002Fclaims come from?** (JWT claims vs. coprocessor-injected.)\n\nThe directives live in the **subgraph schemas**, not in `router.yaml`. The router config only enables\u002Fdisables the feature and (for `@policy`) wires the evaluating plugin. See `references\u002Fconfiguration.md` → Authorization.\n\n### Persisted Query Safelisting (GraphOS PQL)\n\n> **Not the same as APQ.** APQ (`apq`) is a runtime bandwidth optimization that caches *any* operation a client sends — it provides **no** security. Safelisting uses a GraphOS-managed **Persisted Query List (PQL)** that clients register at build time; the router then **rejects operations not on the list**. This is the \"persisted query safelisting\" security control. It is a **GraphOS feature** requiring a router connected to GraphOS (`APOLLO_KEY` + `APOLLO_GRAPH_REF`).\n\nPick a **security level** (increasing restrictiveness):\n\n| Level | Config | Behavior |\n|-------|--------|----------|\n| Audit (recommended first) | `persisted_queries.log_unknown: true` | Logs unregistered operations; rejects nothing. Use to confirm all clients are registered before enforcing. |\n| Safelist | `safelist.enabled: true` | Rejects operations not in the PQL. IDs *and* full strings both accepted if registered. |\n| Safelist, IDs only | `safelist.enabled: true` + `require_id: true` | Rejects unregistered operations **and** any freeform operation string, even if the string is registered. |\n\nThen gather:\n- **Is the router GraphOS-connected?** Safelisting needs the PQL fetched from GraphOS (or `local_manifests` for offline licenses).\n- **Have clients published their operations to the PQL** (via `rover persisted-queries publish` in their CI\u002FCD)? If not, start in audit mode.\n- When enabling `safelist`, **APQ must be disabled** (`apq.enabled: false`) — they are mutually exclusive.\n\nConfig key history: GA `persisted_queries` since v1.32.0 (was `preview_persisted_queries` in v1.25.0–v1.32.0); GA in all v2. See `references\u002Fconfiguration.md` → Persisted Query Safelisting.\n\n### Connectors (v2 only)\n- Subgraph name and source name (used as `connectors.sources.\u003Csubgraph>.\u003Csource>`)\n- Optional `$config` values for connector runtime configuration\n- If migrating old v2 preview config, rename `preview_connectors` to `connectors`\n\n### Operation Limits\nPresent the tuning guidance:\n\n```\nOperation depth limit controls how deeply nested a query can be.\n\n  Router default: 100 (permissive — allows very deep queries)\n  Recommended starting point: 50\n\n  Lower values (15–25) are more secure but will reject legitimate queries\n  in schemas with deep entity relationships or nested fragments.\n  Higher values (75–100) are safer for compatibility but offer less\n  protection against depth-based abuse.\n\n  Tip: Run your router in warn_only mode first to see what depths your\n  real traffic actually uses, then tighten:\n    limits:\n      warn_only: true\n\nWhat max_depth would you like? [default: 50]\n```\n\nThe same principle applies to `max_height`, `max_aliases`, and `max_root_fields`.\n\n### Telemetry\n- OTEL collector endpoint (default: `http:\u002F\u002Fotel-collector:4317`)\n- Prometheus listen port (default: `9090`)\n- Trace sampling rate (default: `0.1` = 10%)\n\n### Traffic Shaping\n- Client-facing rate limit capacity (default: 1000 req\u002Fs)\n- Router timeout (default: 60s)\n- Subgraph timeout (default: 30s)\n\n### Response Caching (v2 only, v2.6.0+)\n\n> **Security: data leakage risk.** Before generating any response cache config, you MUST ask the user which types and fields return user-specific data.  Cached data defaults to shared — subgraph responses without `Cache-Control: private` are visible to all users.  User-specific subgraphs must return `Cache-Control: private` and have `private_id` configured on the router.\n\n- Ask: **Which subgraphs serve user-specific data?** (e.g., accounts, profiles, carts)\n- Ask: **How do you identify users?** (JWT `sub` claim, session token, API key)\n- Redis URL (default: `redis:\u002F\u002Flocalhost:6379`)\n- Default TTL (default: `5m`)\n- Enable active invalidation? If yes: invalidation listen address and shared key\n- Use section template: `templates\u002Fv2\u002Fsections\u002Fresponse-caching.yaml`\n- For security requirements, schema directives, and advanced config: `references\u002Fresponse-caching.md` (start with the Security section)\n\n## Step 5: Generate Config\n\n1. Load the correct version template from `templates\u002F{version}\u002F`\n2. Assemble section templates for supported sectioned features, then merge base-template snippets for APQ\u002Fsubscriptions as needed\n3. Inject user-provided parameters\n4. Add a comment block at the top stating the target version\n\n## Step 6: Validate\n\nRun the [post-generation checklist](validation\u002Fchecklist.md):\n\n- [ ] All env vars referenced in config are documented\n- [ ] CORS origins don't include wildcards (production)\n- [ ] Rate limiting is on `router:` (client-facing), not only `all:` (subgraph)\n- [ ] JWT uses `issuers` (v2) not `issuer` (v1), or vice versa\n- [ ] If production: introspection=false, sandbox=false, subgraph_errors=false\n- [ ] Health check is enabled\n- [ ] Homepage is disabled (production)\n- [ ] Run: `router config validate \u003Cfile>` if Router binary is available\n\n## Required Validation Gate (always run)\n\nAfter generating or editing any `router.yaml`, you MUST:\n\n1. Run `validation\u002Fchecklist.md` and report pass\u002Ffail for each checklist item.\n2. Run `router config validate \u003Cpath-to-router.yaml>` if Router CLI is available.\n3. If Router CLI is unavailable, state that explicitly and still complete the checklist.\n4. Do not present the configuration as final until validation is completed.\n\n## Configuration as Code (git + CI\u002FCD)\n\n`router.yaml` is the router's contract with every request — treat it like application code, not an ops afterthought. Whenever you generate or edit config, steer the user toward this workflow:\n\n- **Commit `router.yaml` to version control.** It should live in git alongside the service, with changes reviewed via pull request. This gives you history, blame, and rollback for the most safety-critical file in the API layer.\n- **Never commit secrets.** Keep `APOLLO_KEY`, JWKS URLs, Redis URLs, and invalidation keys out of the file — reference them with `${env.*}` expansion and inject at deploy time. The committed file should be safe to read by anyone with repo access.\n- **Validate in CI.** Run `router config validate router.yaml` on every PR so a malformed or version-mismatched config fails the build before it ships. Pin the Router version used in CI to the version you deploy.\n- **Pair config changes with schema checks.** Schema changes flow through `rover subgraph check` \u002F `rover subgraph publish` (the `rover` skill); config changes flow through this validate-in-CI gate. Both gate the same deploy.\n- **Promote the same file across environments.** Differences between dev and prod should be expressed through env vars, not divergent committed files, so what you reviewed is what runs.\n\nA minimal CI step (provide actual commands only if asked):\n\n```yaml\n# Validate router config on every pull request\n- run: router config validate router.yaml\n```\n\n## Step 7: Conditional Next Steps Handoff\n\nAfter answering any Apollo Router request (config generation, edits, validation, or general Router guidance), decide whether the user already has runnable prerequisites:\n\n- GraphOS-managed path: `APOLLO_KEY` + `APOLLO_GRAPH_REF`, or\n- Local path: a composed `supergraph.graphql` plus reachable subgraphs\n\nIf prerequisites are already present, do not add extra handoff text.\n\nIf prerequisites are missing or unknown, end with a concise **Next steps** handoff (1-3 lines max) that is skill-first and command-free:\n\n1. Suggest the `rover` skill to compose or fetch the supergraph schema.\n2. Suggest continuing with `apollo-router` once the supergraph is ready to validate and run with the generated config.\n3. If subgraphs are missing, suggest `apollo-server`, `graphql-schema`, and `graphql-operations` skills to scaffold and test.\n\nDo not include raw shell commands in this handoff unless the user explicitly asks for commands.\n\n## Quick Start (skill-first)\n\n1. Use this `apollo-router` skill to generate or refine `router.yaml` for your environment.\n2. Choose a runtime path:\n   - GraphOS-managed path: provide `APOLLO_KEY` and `APOLLO_GRAPH_REF` (no local supergraph composition required).\n   - Local supergraph path: use `graphql-schema` + `apollo-server` to define\u002Frun subgraphs, then use `graphql-operations` for smoke tests, then use the `rover` skill to compose or fetch `supergraph.graphql`.\n3. Use this `apollo-router` skill to validate readiness (`validation\u002Fchecklist.md`) and walk through runtime startup inputs.\n\nDefault endpoint remains `http:\u002F\u002Flocalhost:4000` when using standard Router listen defaults.\n\nIf the user asks for executable shell commands, provide them on request. Otherwise keep Quick Start guidance skill-oriented.\n\n## Running Modes\n\n| Mode | Command | Use Case |\n|------|---------|----------|\n| Local schema | `router --supergraph .\u002Fschema.graphql` | Development, CI\u002FCD |\n| GraphOS managed | `APOLLO_KEY=... APOLLO_GRAPH_REF=my-graph@prod router` | Production with auto-updates |\n| Development | `router --dev --supergraph .\u002Fschema.graphql` | Local development |\n| Hot reload | `router --hot-reload --supergraph .\u002Fschema.graphql` | Schema changes without restart |\n\n## Environment Variables\n\n| Variable | Description |\n|----------|-------------|\n| `APOLLO_KEY` | API key for GraphOS |\n| `APOLLO_GRAPH_REF` | Graph reference (`graph-id@variant`) |\n| `APOLLO_ROUTER_CONFIG_PATH` | Path to `router.yaml` |\n| `APOLLO_ROUTER_SUPERGRAPH_PATH` | Path to supergraph schema |\n| `APOLLO_ROUTER_LOG` | Log level (off, error, warn, info, debug, trace) |\n| `APOLLO_ROUTER_LISTEN_ADDRESS` | Override listen address |\n\n## Reference Files\n\n- [Configuration](references\u002Fconfiguration.md) — YAML configuration reference\n- [Headers](references\u002Fheaders.md) — Header propagation and manipulation\n- [Plugins](references\u002Fplugins.md) — Rhai scripts and coprocessors\n- [Telemetry](references\u002Ftelemetry.md) — Tracing, metrics, and logging\n- [Connectors](references\u002Fconnectors.md) — Router v2 connectors configuration\n- [Response Caching](references\u002Fresponse-caching.md) — Entity\u002Froot-field caching, invalidation, and observability (v2 only)\n- [Troubleshooting](references\u002Ftroubleshooting.md) — Common issues and solutions\n- [Divergence Map](divergence-map.md) — v1 ↔ v2 config differences\n- [Validation Checklist](validation\u002Fchecklist.md) — Post-generation checks\n\n## CLI Reference\n\n```\nrouter [OPTIONS]\n\nOptions:\n  -s, --supergraph \u003CPATH>    Path to supergraph schema file\n  -c, --config \u003CPATH>        Path to router.yaml configuration\n      --dev                  Enable development mode\n      --hot-reload           Watch for schema changes\n      --log \u003CLEVEL>          Log level (default: info)\n      --listen \u003CADDRESS>     Override listen address\n  -V, --version              Print version\n  -h, --help                 Print help\n```\n\n## Ground Rules\n\n- ALWAYS determine the target Router version (v1 or v2) before generating config\n- DEFAULT to v2 for new projects\n- ALWAYS include a comment block at top of generated config stating the target version\n- ALWAYS use `--dev` mode for local development (enables introspection and sandbox)\n- ALWAYS disable introspection, sandbox, and homepage in production\n- PREFER GraphOS managed mode for production (automatic updates, metrics)\n- USE `--hot-reload` for local development with file-based schemas\n- NEVER expose `APOLLO_KEY` in logs or version control\n- USE environment variables (`${env.VAR}`) for all secrets and sensitive config\n- PREFER YAML configuration over command-line arguments for complex setups\n- TEST configuration changes locally before deploying to production\n- WARN if user enables `allow_any_origin` or wildcard CORS in production\n- RECOMMEND `router config upgrade router.yaml` for v1 → v2 migration instead of regenerating from scratch\n- MUST run `validation\u002Fchecklist.md` after every router config generation or edit\n- MUST run `router config validate \u003Cfile>` when Router CLI is available\n- MUST report when CLI validation could not run (for example, Router binary missing)\n- MUST append a brief conditional handoff when runtime prerequisites are missing or unknown\n- MUST make this handoff skill-first and avoid raw shell commands unless the user explicitly requests commands\n- MUST keep Quick Start guidance skill-first and command-free unless the user explicitly requests commands\n- MUST state that Rover is required only for the local supergraph path; GraphOS-managed runtime does not require local Rover composition\n- USE `max_depth: 50` as the default starting point, not 15 (too aggressive) or 100 (too permissive)\n- RECOMMEND `warn_only: true` for initial limits rollout to observe real traffic before enforcing\n- ONLY offer Response Caching when `ROUTER_VERSION=v2` (requires v2.6.0+)\n- ALWAYS use `${env.*}` for Redis URLs, passwords, and invalidation shared keys\n- NEVER enable `response_cache.debug: true` in production config\n- RECOMMEND combining Cache-Control headers (passive TTL) with @cacheTag (active invalidation) for production\n- ALWAYS ask which fields return user-specific data before generating response cache config — never assume all data is safe to cache as shared\n- ALWAYS configure `private_id` for subgraphs that serve user-specific data, and ensure those subgraphs return `Cache-Control: private` (via `@cacheControl(scope: PRIVATE)` in Apollo Server, or by setting the header directly in other frameworks)\n- NEVER generate response cache config without addressing private data — if the user says \"no user-specific data\", confirm explicitly before proceeding\n- ALWAYS bind the invalidation endpoint to `127.0.0.1`, NEVER `0.0.0.0` in production\n- NEVER conflate APQ with persisted-query safelisting — APQ (`apq`) is a bandwidth optimization with no security value; safelisting (`persisted_queries.safelist`) is the operation allowlist. If a user asks to \"lock down which queries can run\", point them to safelisting, not APQ\n- ALWAYS disable APQ (`apq.enabled: false`) when enabling `persisted_queries.safelist` — they are mutually exclusive\n- RECOMMEND starting persisted queries in audit mode (`log_unknown: true`) to confirm all clients are registered before turning on `safelist.enabled`\n- STATE that persisted-query safelisting requires a GraphOS-connected router (PQL fetched via `APOLLO_KEY` + `APOLLO_GRAPH_REF`, or `local_manifests` for offline licenses)\n- USE `persisted_queries` (GA, v1.32.0+ and all v2), NOT `preview_persisted_queries` (v1.25.0–v1.32.0)\n- TREAT global `authorization.require_authentication` and declarative directives as different layers: the former gates the whole request, the latter (`@authenticated` \u002F `@requiresScopes` \u002F `@policy`) does field- and type-level filtering\n- STATE that declarative authorization directives require a GraphOS-connected router (v1.29.1+; Developer\u002FStandard plans need v2.6.0+) and a claims source (JWT auth or a coprocessor populating `apollo::authentication::jwt_claims`)\n- NOTE that authorization directives are ENABLED BY DEFAULT — `authorization.directives.enabled: false` only turns them off; never imply config is required to \"turn them on\"\n- STATE that `@policy` additionally requires a Rhai script or coprocessor at the Supergraph stage to evaluate `apollo::authorization::required_policies`\n- PLACE authorization directives in subgraph schemas, NEVER in `router.yaml` — router config only enables\u002Fdisables the feature\n- RECOMMEND committing `router.yaml` to version control and running `router config validate` in CI on every PR, with all secrets referenced via `${env.*}` and injected at deploy time\n- NEVER commit secrets (`APOLLO_KEY`, JWKS\u002FRedis URLs, invalidation keys) to the config file; the committed `router.yaml` must be safe to share with anyone holding repo access\n",{"data":38,"body":43},{"name":4,"description":6,"license":27,"compatibility":39,"metadata":40,"allowed-tools":42},"Linux\u002FmacOS\u002FWindows. Requires a composed supergraph schema from Rover or GraphOS.",{"author":11,"version":41},"2.5.0","Bash(router:*) Bash(.\u002Frouter:*) Bash(rover:*) Bash(curl:*) Bash(docker:*) Read Write Edit Glob Grep",{"type":44,"children":45},"root",[46,55,61,72,79,91,104,120,129,142,148,167,190,195,216,222,227,383,389,394,498,504,520,526,555,561,625,630,691,696,740,775,781,852,864,982,987,1052,1080,1086,1131,1137,1142,1151,1177,1182,1222,1227,1245,1251,1287,1373,1379,1409,1415,1428,1542,1548,1560,1597,1603,1613,1719,1724,1770,1776,1781,1815,1820,1832,1886,1891,1897,2002,2015,2020,2026,2140,2146,2280,2286,2384,2390,2399,2405,2921],{"type":47,"tag":48,"props":49,"children":51},"element","h1",{"id":50},"apollo-router-config-generator",[52],{"type":53,"value":54},"text","Apollo Router Config Generator",{"type":47,"tag":56,"props":57,"children":58},"p",{},[59],{"type":53,"value":60},"Apollo Router is a high-performance graph router written in Rust for running Apollo Federation 2 supergraphs. It sits in front of your subgraphs and handles query planning, execution, and response composition.",{"type":47,"tag":56,"props":62,"children":63},{},[64,70],{"type":47,"tag":65,"props":66,"children":67},"strong",{},[68],{"type":53,"value":69},"This skill generates version-correct configuration.",{"type":53,"value":71}," Router v1 and v2 have incompatible config schemas in several critical sections (CORS, JWT auth, connectors). Always determine the target version before generating any config.",{"type":47,"tag":73,"props":74,"children":76},"h2",{"id":75},"step-1-version-selection",[77],{"type":53,"value":78},"Step 1: Version Selection",{"type":47,"tag":56,"props":80,"children":81},{},[82,84,89],{"type":53,"value":83},"Ask the user ",{"type":47,"tag":65,"props":85,"children":86},{},[87],{"type":53,"value":88},"before generating any config",{"type":53,"value":90},":",{"type":47,"tag":92,"props":93,"children":97},"pre",{"className":94,"code":96,"language":53},[95],"language-text","Which Apollo Router version are you targeting?\n\n  [1] Router v2.x (recommended — current LTS, required for Connectors)\n  [2] Router v1.x (legacy — end-of-support announced, security patches only)\n  [3] Not sure — help me decide\n",[98],{"type":47,"tag":99,"props":100,"children":102},"code",{"__ignoreMap":101},"",[103],{"type":53,"value":96},{"type":47,"tag":56,"props":105,"children":106},{},[107,109,118],{"type":53,"value":108},"If the user picks ",{"type":47,"tag":65,"props":110,"children":111},{},[112],{"type":47,"tag":113,"props":114,"children":115},"span",{},[116],{"type":53,"value":117},"3",{"type":53,"value":119},", display:",{"type":47,"tag":92,"props":121,"children":124},{"className":122,"code":123,"language":53},[95],"Quick guide:\n\n  • Pick v2 if: you're starting fresh, using Apollo Connectors for REST APIs,\n    or want backpressure-based overload protection.\n  • Pick v1 if: you have an existing deployment and haven't migrated yet.\n    Note: Apollo ended active support for v1.x. The v2.10 LTS (Dec 2025)\n    is the current baseline. Migration is strongly recommended.\n\n  Tip: If you have an existing router.yaml, you can auto-migrate it:\n    router config upgrade router.yaml\n",[125],{"type":47,"tag":99,"props":126,"children":127},{"__ignoreMap":101},[128],{"type":53,"value":123},{"type":47,"tag":56,"props":130,"children":131},{},[132,134,140],{"type":53,"value":133},"Store the selection as ",{"type":47,"tag":99,"props":135,"children":137},{"className":136},[],[138],{"type":53,"value":139},"ROUTER_VERSION=v1|v2",{"type":53,"value":141}," to gate all subsequent template generation.",{"type":47,"tag":73,"props":143,"children":145},{"id":144},"step-2-environment-selection",[146],{"type":53,"value":147},"Step 2: Environment Selection",{"type":47,"tag":56,"props":149,"children":150},{},[151,153,158,160,165],{"type":53,"value":152},"Ask: ",{"type":47,"tag":65,"props":154,"children":155},{},[156],{"type":53,"value":157},"Production",{"type":53,"value":159}," or ",{"type":47,"tag":65,"props":161,"children":162},{},[163],{"type":53,"value":164},"Development",{"type":53,"value":166},"?",{"type":47,"tag":168,"props":169,"children":170},"ul",{},[171,181],{"type":47,"tag":172,"props":173,"children":174},"li",{},[175,179],{"type":47,"tag":65,"props":176,"children":177},{},[178],{"type":53,"value":157},{"type":53,"value":180},": security-hardened defaults (introspection off, sandbox off, homepage off, subgraph errors hidden, auth required, health check on)",{"type":47,"tag":172,"props":182,"children":183},{},[184,188],{"type":47,"tag":65,"props":185,"children":186},{},[187],{"type":53,"value":164},{"type":53,"value":189},": open defaults (introspection on, sandbox on, errors exposed, text logging)",{"type":47,"tag":56,"props":191,"children":192},{},[193],{"type":53,"value":194},"Load the appropriate base template from:",{"type":47,"tag":168,"props":196,"children":197},{},[198,207],{"type":47,"tag":172,"props":199,"children":200},{},[201],{"type":47,"tag":99,"props":202,"children":204},{"className":203},[],[205],{"type":53,"value":206},"templates\u002F{version}\u002Fproduction.yaml",{"type":47,"tag":172,"props":208,"children":209},{},[210],{"type":47,"tag":99,"props":211,"children":213},{"className":212},[],[214],{"type":53,"value":215},"templates\u002F{version}\u002Fdevelopment.yaml",{"type":47,"tag":73,"props":217,"children":219},{"id":218},"step-3-feature-selection",[220],{"type":53,"value":221},"Step 3: Feature Selection",{"type":47,"tag":56,"props":223,"children":224},{},[225],{"type":53,"value":226},"Ask which features to include:",{"type":47,"tag":168,"props":228,"children":231},{"className":229},[230],"contains-task-list",[232,245,277,286,295,304,313,322,331,356,365,374],{"type":47,"tag":172,"props":233,"children":236},{"className":234},[235],"task-list-item",[237,243],{"type":47,"tag":238,"props":239,"children":242},"input",{"disabled":240,"type":241},true,"checkbox",[],{"type":53,"value":244}," JWT Authentication",{"type":47,"tag":172,"props":246,"children":248},{"className":247},[235],[249,252,254,260,262,268,269,275],{"type":47,"tag":238,"props":250,"children":251},{"disabled":240,"type":241},[],{"type":53,"value":253}," Declarative Authorization (field-level ",{"type":47,"tag":99,"props":255,"children":257},{"className":256},[],[258],{"type":53,"value":259},"@authenticated",{"type":53,"value":261}," \u002F ",{"type":47,"tag":99,"props":263,"children":265},{"className":264},[],[266],{"type":53,"value":267},"@requiresScopes",{"type":53,"value":261},{"type":47,"tag":99,"props":270,"children":272},{"className":271},[],[273],{"type":53,"value":274},"@policy",{"type":53,"value":276}," directives — requires GraphOS + request claims)",{"type":47,"tag":172,"props":278,"children":280},{"className":279},[235],[281,284],{"type":47,"tag":238,"props":282,"children":283},{"disabled":240,"type":241},[],{"type":53,"value":285}," CORS (almost always yes for browser clients)",{"type":47,"tag":172,"props":287,"children":289},{"className":288},[235],[290,293],{"type":47,"tag":238,"props":291,"children":292},{"disabled":240,"type":241},[],{"type":53,"value":294}," Operation Limits",{"type":47,"tag":172,"props":296,"children":298},{"className":297},[235],[299,302],{"type":47,"tag":238,"props":300,"children":301},{"disabled":240,"type":241},[],{"type":53,"value":303}," Traffic Shaping \u002F Rate Limiting",{"type":47,"tag":172,"props":305,"children":307},{"className":306},[235],[308,311],{"type":47,"tag":238,"props":309,"children":310},{"disabled":240,"type":241},[],{"type":53,"value":312}," Telemetry (Prometheus, OTLP tracing, JSON logging)",{"type":47,"tag":172,"props":314,"children":316},{"className":315},[235],[317,320],{"type":47,"tag":238,"props":318,"children":319},{"disabled":240,"type":241},[],{"type":53,"value":321}," APQ (Automatic Persisted Queries — performance\u002Fbandwidth only, NOT a security control)",{"type":47,"tag":172,"props":323,"children":325},{"className":324},[235],[326,329],{"type":47,"tag":238,"props":327,"children":328},{"disabled":240,"type":241},[],{"type":53,"value":330}," Persisted Query Safelisting (GraphOS PQL operation allowlist — a security control; distinct from APQ)",{"type":47,"tag":172,"props":332,"children":334},{"className":333},[235],[335,338,340,346,348,354],{"type":47,"tag":238,"props":336,"children":337},{"disabled":240,"type":241},[],{"type":53,"value":339}," Connectors (REST API integration — Router v2 only; GA key is ",{"type":47,"tag":99,"props":341,"children":343},{"className":342},[],[344],{"type":53,"value":345},"connectors",{"type":53,"value":347},", early v2 preview key was ",{"type":47,"tag":99,"props":349,"children":351},{"className":350},[],[352],{"type":53,"value":353},"preview_connectors",{"type":53,"value":355},")",{"type":47,"tag":172,"props":357,"children":359},{"className":358},[235],[360,363],{"type":47,"tag":238,"props":361,"children":362},{"disabled":240,"type":241},[],{"type":53,"value":364}," Subscriptions",{"type":47,"tag":172,"props":366,"children":368},{"className":367},[235],[369,372],{"type":47,"tag":238,"props":370,"children":371},{"disabled":240,"type":241},[],{"type":53,"value":373}," Header Propagation",{"type":47,"tag":172,"props":375,"children":377},{"className":376},[235],[378,381],{"type":47,"tag":238,"props":379,"children":380},{"disabled":240,"type":241},[],{"type":53,"value":382}," Response Caching (entity + root field caching with Redis — Router v2 only, v2.6.0+)",{"type":47,"tag":73,"props":384,"children":386},{"id":385},"step-4-gather-parameters",[387],{"type":53,"value":388},"Step 4: Gather Parameters",{"type":47,"tag":56,"props":390,"children":391},{},[392],{"type":53,"value":393},"For each selected feature, collect required values.",{"type":47,"tag":168,"props":395,"children":396},{},[397,455,468,486],{"type":47,"tag":172,"props":398,"children":399},{},[400,402,408,410,416,418,424,425,431,432,438,439,445,447,453],{"type":53,"value":401},"Use section templates from ",{"type":47,"tag":99,"props":403,"children":405},{"className":404},[],[406],{"type":53,"value":407},"templates\u002F{version}\u002Fsections\u002F",{"type":53,"value":409}," for ",{"type":47,"tag":99,"props":411,"children":413},{"className":412},[],[414],{"type":53,"value":415},"auth",{"type":53,"value":417},", ",{"type":47,"tag":99,"props":419,"children":421},{"className":420},[],[422],{"type":53,"value":423},"cors",{"type":53,"value":417},{"type":47,"tag":99,"props":426,"children":428},{"className":427},[],[429],{"type":53,"value":430},"headers",{"type":53,"value":417},{"type":47,"tag":99,"props":433,"children":435},{"className":434},[],[436],{"type":53,"value":437},"limits",{"type":53,"value":417},{"type":47,"tag":99,"props":440,"children":442},{"className":441},[],[443],{"type":53,"value":444},"telemetry",{"type":53,"value":446},", and ",{"type":47,"tag":99,"props":448,"children":450},{"className":449},[],[451],{"type":53,"value":452},"traffic-shaping",{"type":53,"value":454},".",{"type":47,"tag":172,"props":456,"children":457},{},[458,460,466],{"type":53,"value":459},"For Connectors in v2, use ",{"type":47,"tag":99,"props":461,"children":463},{"className":462},[],[464],{"type":53,"value":465},"templates\u002Fv2\u002Fsections\u002Fconnectors.yaml",{"type":53,"value":467}," as the source.",{"type":47,"tag":172,"props":469,"children":470},{},[471,473,478,479,484],{"type":53,"value":472},"For APQ and subscriptions, copy the snippet from the selected base template (",{"type":47,"tag":99,"props":474,"children":476},{"className":475},[],[477],{"type":53,"value":206},{"type":53,"value":159},{"type":47,"tag":99,"props":480,"children":482},{"className":481},[],[483],{"type":53,"value":215},{"type":53,"value":485},") or from references.",{"type":47,"tag":172,"props":487,"children":488},{},[489,491,497],{"type":53,"value":490},"Only offer Connectors when ",{"type":47,"tag":99,"props":492,"children":494},{"className":493},[],[495],{"type":53,"value":496},"ROUTER_VERSION=v2",{"type":53,"value":454},{"type":47,"tag":499,"props":500,"children":501},"h3",{"id":423},[502],{"type":53,"value":503},"CORS",{"type":47,"tag":168,"props":505,"children":506},{},[507],{"type":47,"tag":172,"props":508,"children":509},{},[510,512,518],{"type":53,"value":511},"List of allowed origins (never use ",{"type":47,"tag":99,"props":513,"children":515},{"className":514},[],[516],{"type":53,"value":517},"\"*\"",{"type":53,"value":519}," for production)",{"type":47,"tag":499,"props":521,"children":523},{"id":522},"jwt-authentication",[524],{"type":53,"value":525},"JWT Authentication",{"type":47,"tag":168,"props":527,"children":528},{},[529,534],{"type":47,"tag":172,"props":530,"children":531},{},[532],{"type":53,"value":533},"JWKS URL",{"type":47,"tag":172,"props":535,"children":536},{},[537,539,545,547,553],{"type":53,"value":538},"Issuer(s) — note: v1 uses singular ",{"type":47,"tag":99,"props":540,"children":542},{"className":541},[],[543],{"type":53,"value":544},"issuer",{"type":53,"value":546},", v2 uses plural ",{"type":47,"tag":99,"props":548,"children":550},{"className":549},[],[551],{"type":53,"value":552},"issuers",{"type":53,"value":554}," array",{"type":47,"tag":499,"props":556,"children":558},{"id":557},"declarative-authorization-field-level",[559],{"type":53,"value":560},"Declarative Authorization (field-level)",{"type":47,"tag":562,"props":563,"children":564},"blockquote",{},[565],{"type":47,"tag":56,"props":566,"children":567},{},[568,570,575,577,582,583,588,589,594,596,602,604,609,611,616,618,624],{"type":53,"value":569},"Field- and type-level access control enforced ",{"type":47,"tag":65,"props":571,"children":572},{},[573],{"type":53,"value":574},"in the router",{"type":53,"value":576},", via the ",{"type":47,"tag":99,"props":578,"children":580},{"className":579},[],[581],{"type":53,"value":259},{"type":53,"value":417},{"type":47,"tag":99,"props":584,"children":586},{"className":585},[],[587],{"type":53,"value":267},{"type":53,"value":446},{"type":47,"tag":99,"props":590,"children":592},{"className":591},[],[593],{"type":53,"value":274},{"type":53,"value":595}," directives applied in subgraph schemas. This is the layer that the global ",{"type":47,"tag":99,"props":597,"children":599},{"className":598},[],[600],{"type":53,"value":601},"authorization.require_authentication",{"type":53,"value":603}," gate cannot express. It is a ",{"type":47,"tag":65,"props":605,"children":606},{},[607],{"type":53,"value":608},"GraphOS feature",{"type":53,"value":610}," (Enterprise; Developer\u002FStandard plans require Router v2.6.0+) and requires a router connected to GraphOS. Directives are ",{"type":47,"tag":65,"props":612,"children":613},{},[614],{"type":53,"value":615},"enabled by default",{"type":53,"value":617}," — config only turns them ",{"type":47,"tag":619,"props":620,"children":621},"em",{},[622],{"type":53,"value":623},"off",{"type":53,"value":454},{"type":47,"tag":56,"props":626,"children":627},{},[628],{"type":53,"value":629},"Confirm prerequisites before recommending these:",{"type":47,"tag":168,"props":631,"children":632},{},[633,643,668],{"type":47,"tag":172,"props":634,"children":635},{},[636,641],{"type":47,"tag":65,"props":637,"children":638},{},[639],{"type":53,"value":640},"Router connected to GraphOS",{"type":53,"value":642}," (Router v1.29.1+; Developer\u002FStandard plans need v2.6.0+).",{"type":47,"tag":172,"props":644,"children":645},{},[646,651,653,659,661,666],{"type":47,"tag":65,"props":647,"children":648},{},[649],{"type":53,"value":650},"A claims source.",{"type":53,"value":652}," Directives evaluate the claims at the ",{"type":47,"tag":99,"props":654,"children":656},{"className":655},[],[657],{"type":53,"value":658},"apollo::authentication::jwt_claims",{"type":53,"value":660}," context key. Populate it via JWT authentication (configure that feature too) ",{"type":47,"tag":65,"props":662,"children":663},{},[664],{"type":53,"value":665},"or",{"type":53,"value":667}," a coprocessor that injects claims.",{"type":47,"tag":172,"props":669,"children":670},{},[671,681,683,689],{"type":47,"tag":65,"props":672,"children":673},{},[674,679],{"type":47,"tag":99,"props":675,"children":677},{"className":676},[],[678],{"type":53,"value":274},{"type":53,"value":680}," additionally requires a Supergraph plugin",{"type":53,"value":682}," (Rhai script or coprocessor) to evaluate each policy — the router extracts required policies into ",{"type":47,"tag":99,"props":684,"children":686},{"className":685},[],[687],{"type":53,"value":688},"apollo::authorization::required_policies",{"type":53,"value":690}," but does not decide them itself.",{"type":47,"tag":56,"props":692,"children":693},{},[694],{"type":53,"value":695},"Ask:",{"type":47,"tag":168,"props":697,"children":698},{},[699,730],{"type":47,"tag":172,"props":700,"children":701},{},[702,707,709,714,716,721,723,728],{"type":47,"tag":65,"props":703,"children":704},{},[705],{"type":53,"value":706},"Which fields\u002Ftypes need protection, and at what level?",{"type":53,"value":708}," (",{"type":47,"tag":99,"props":710,"children":712},{"className":711},[],[713],{"type":53,"value":259},{"type":53,"value":715}," = any valid identity; ",{"type":47,"tag":99,"props":717,"children":719},{"className":718},[],[720],{"type":53,"value":267},{"type":53,"value":722}," = specific scopes; ",{"type":47,"tag":99,"props":724,"children":726},{"className":725},[],[727],{"type":53,"value":274},{"type":53,"value":729}," = custom logic.)",{"type":47,"tag":172,"props":731,"children":732},{},[733,738],{"type":47,"tag":65,"props":734,"children":735},{},[736],{"type":53,"value":737},"Where do scopes\u002Fclaims come from?",{"type":53,"value":739}," (JWT claims vs. coprocessor-injected.)",{"type":47,"tag":56,"props":741,"children":742},{},[743,745,750,752,758,760,765,767,773],{"type":53,"value":744},"The directives live in the ",{"type":47,"tag":65,"props":746,"children":747},{},[748],{"type":53,"value":749},"subgraph schemas",{"type":53,"value":751},", not in ",{"type":47,"tag":99,"props":753,"children":755},{"className":754},[],[756],{"type":53,"value":757},"router.yaml",{"type":53,"value":759},". The router config only enables\u002Fdisables the feature and (for ",{"type":47,"tag":99,"props":761,"children":763},{"className":762},[],[764],{"type":53,"value":274},{"type":53,"value":766},") wires the evaluating plugin. See ",{"type":47,"tag":99,"props":768,"children":770},{"className":769},[],[771],{"type":53,"value":772},"references\u002Fconfiguration.md",{"type":53,"value":774}," → Authorization.",{"type":47,"tag":499,"props":776,"children":778},{"id":777},"persisted-query-safelisting-graphos-pql",[779],{"type":53,"value":780},"Persisted Query Safelisting (GraphOS PQL)",{"type":47,"tag":562,"props":782,"children":783},{},[784],{"type":47,"tag":56,"props":785,"children":786},{},[787,792,794,800,802,807,809,814,816,821,823,828,830,834,836,842,844,850],{"type":47,"tag":65,"props":788,"children":789},{},[790],{"type":53,"value":791},"Not the same as APQ.",{"type":53,"value":793}," APQ (",{"type":47,"tag":99,"props":795,"children":797},{"className":796},[],[798],{"type":53,"value":799},"apq",{"type":53,"value":801},") is a runtime bandwidth optimization that caches ",{"type":47,"tag":619,"props":803,"children":804},{},[805],{"type":53,"value":806},"any",{"type":53,"value":808}," operation a client sends — it provides ",{"type":47,"tag":65,"props":810,"children":811},{},[812],{"type":53,"value":813},"no",{"type":53,"value":815}," security. Safelisting uses a GraphOS-managed ",{"type":47,"tag":65,"props":817,"children":818},{},[819],{"type":53,"value":820},"Persisted Query List (PQL)",{"type":53,"value":822}," that clients register at build time; the router then ",{"type":47,"tag":65,"props":824,"children":825},{},[826],{"type":53,"value":827},"rejects operations not on the list",{"type":53,"value":829},". This is the \"persisted query safelisting\" security control. It is a ",{"type":47,"tag":65,"props":831,"children":832},{},[833],{"type":53,"value":608},{"type":53,"value":835}," requiring a router connected to GraphOS (",{"type":47,"tag":99,"props":837,"children":839},{"className":838},[],[840],{"type":53,"value":841},"APOLLO_KEY",{"type":53,"value":843}," + ",{"type":47,"tag":99,"props":845,"children":847},{"className":846},[],[848],{"type":53,"value":849},"APOLLO_GRAPH_REF",{"type":53,"value":851},").",{"type":47,"tag":56,"props":853,"children":854},{},[855,857,862],{"type":53,"value":856},"Pick a ",{"type":47,"tag":65,"props":858,"children":859},{},[860],{"type":53,"value":861},"security level",{"type":53,"value":863}," (increasing restrictiveness):",{"type":47,"tag":865,"props":866,"children":867},"table",{},[868,892],{"type":47,"tag":869,"props":870,"children":871},"thead",{},[872],{"type":47,"tag":873,"props":874,"children":875},"tr",{},[876,882,887],{"type":47,"tag":877,"props":878,"children":879},"th",{},[880],{"type":53,"value":881},"Level",{"type":47,"tag":877,"props":883,"children":884},{},[885],{"type":53,"value":886},"Config",{"type":47,"tag":877,"props":888,"children":889},{},[890],{"type":53,"value":891},"Behavior",{"type":47,"tag":893,"props":894,"children":895},"tbody",{},[896,919,948],{"type":47,"tag":873,"props":897,"children":898},{},[899,905,914],{"type":47,"tag":900,"props":901,"children":902},"td",{},[903],{"type":53,"value":904},"Audit (recommended first)",{"type":47,"tag":900,"props":906,"children":907},{},[908],{"type":47,"tag":99,"props":909,"children":911},{"className":910},[],[912],{"type":53,"value":913},"persisted_queries.log_unknown: true",{"type":47,"tag":900,"props":915,"children":916},{},[917],{"type":53,"value":918},"Logs unregistered operations; rejects nothing. Use to confirm all clients are registered before enforcing.",{"type":47,"tag":873,"props":920,"children":921},{},[922,927,936],{"type":47,"tag":900,"props":923,"children":924},{},[925],{"type":53,"value":926},"Safelist",{"type":47,"tag":900,"props":928,"children":929},{},[930],{"type":47,"tag":99,"props":931,"children":933},{"className":932},[],[934],{"type":53,"value":935},"safelist.enabled: true",{"type":47,"tag":900,"props":937,"children":938},{},[939,941,946],{"type":53,"value":940},"Rejects operations not in the PQL. IDs ",{"type":47,"tag":619,"props":942,"children":943},{},[944],{"type":53,"value":945},"and",{"type":53,"value":947}," full strings both accepted if registered.",{"type":47,"tag":873,"props":949,"children":950},{},[951,956,971],{"type":47,"tag":900,"props":952,"children":953},{},[954],{"type":53,"value":955},"Safelist, IDs only",{"type":47,"tag":900,"props":957,"children":958},{},[959,964,965],{"type":47,"tag":99,"props":960,"children":962},{"className":961},[],[963],{"type":53,"value":935},{"type":53,"value":843},{"type":47,"tag":99,"props":966,"children":968},{"className":967},[],[969],{"type":53,"value":970},"require_id: true",{"type":47,"tag":900,"props":972,"children":973},{},[974,976,980],{"type":53,"value":975},"Rejects unregistered operations ",{"type":47,"tag":65,"props":977,"children":978},{},[979],{"type":53,"value":945},{"type":53,"value":981}," any freeform operation string, even if the string is registered.",{"type":47,"tag":56,"props":983,"children":984},{},[985],{"type":53,"value":986},"Then gather:",{"type":47,"tag":168,"props":988,"children":989},{},[990,1008,1026],{"type":47,"tag":172,"props":991,"children":992},{},[993,998,1000,1006],{"type":47,"tag":65,"props":994,"children":995},{},[996],{"type":53,"value":997},"Is the router GraphOS-connected?",{"type":53,"value":999}," Safelisting needs the PQL fetched from GraphOS (or ",{"type":47,"tag":99,"props":1001,"children":1003},{"className":1002},[],[1004],{"type":53,"value":1005},"local_manifests",{"type":53,"value":1007}," for offline licenses).",{"type":47,"tag":172,"props":1009,"children":1010},{},[1011,1016,1018,1024],{"type":47,"tag":65,"props":1012,"children":1013},{},[1014],{"type":53,"value":1015},"Have clients published their operations to the PQL",{"type":53,"value":1017}," (via ",{"type":47,"tag":99,"props":1019,"children":1021},{"className":1020},[],[1022],{"type":53,"value":1023},"rover persisted-queries publish",{"type":53,"value":1025}," in their CI\u002FCD)? If not, start in audit mode.",{"type":47,"tag":172,"props":1027,"children":1028},{},[1029,1031,1037,1038,1043,1044,1050],{"type":53,"value":1030},"When enabling ",{"type":47,"tag":99,"props":1032,"children":1034},{"className":1033},[],[1035],{"type":53,"value":1036},"safelist",{"type":53,"value":417},{"type":47,"tag":65,"props":1039,"children":1040},{},[1041],{"type":53,"value":1042},"APQ must be disabled",{"type":53,"value":708},{"type":47,"tag":99,"props":1045,"children":1047},{"className":1046},[],[1048],{"type":53,"value":1049},"apq.enabled: false",{"type":53,"value":1051},") — they are mutually exclusive.",{"type":47,"tag":56,"props":1053,"children":1054},{},[1055,1057,1063,1065,1071,1073,1078],{"type":53,"value":1056},"Config key history: GA ",{"type":47,"tag":99,"props":1058,"children":1060},{"className":1059},[],[1061],{"type":53,"value":1062},"persisted_queries",{"type":53,"value":1064}," since v1.32.0 (was ",{"type":47,"tag":99,"props":1066,"children":1068},{"className":1067},[],[1069],{"type":53,"value":1070},"preview_persisted_queries",{"type":53,"value":1072}," in v1.25.0–v1.32.0); GA in all v2. See ",{"type":47,"tag":99,"props":1074,"children":1076},{"className":1075},[],[1077],{"type":53,"value":772},{"type":53,"value":1079}," → Persisted Query Safelisting.",{"type":47,"tag":499,"props":1081,"children":1083},{"id":1082},"connectors-v2-only",[1084],{"type":53,"value":1085},"Connectors (v2 only)",{"type":47,"tag":168,"props":1087,"children":1088},{},[1089,1101,1114],{"type":47,"tag":172,"props":1090,"children":1091},{},[1092,1094,1100],{"type":53,"value":1093},"Subgraph name and source name (used as ",{"type":47,"tag":99,"props":1095,"children":1097},{"className":1096},[],[1098],{"type":53,"value":1099},"connectors.sources.\u003Csubgraph>.\u003Csource>",{"type":53,"value":355},{"type":47,"tag":172,"props":1102,"children":1103},{},[1104,1106,1112],{"type":53,"value":1105},"Optional ",{"type":47,"tag":99,"props":1107,"children":1109},{"className":1108},[],[1110],{"type":53,"value":1111},"$config",{"type":53,"value":1113}," values for connector runtime configuration",{"type":47,"tag":172,"props":1115,"children":1116},{},[1117,1119,1124,1126],{"type":53,"value":1118},"If migrating old v2 preview config, rename ",{"type":47,"tag":99,"props":1120,"children":1122},{"className":1121},[],[1123],{"type":53,"value":353},{"type":53,"value":1125}," to ",{"type":47,"tag":99,"props":1127,"children":1129},{"className":1128},[],[1130],{"type":53,"value":345},{"type":47,"tag":499,"props":1132,"children":1134},{"id":1133},"operation-limits",[1135],{"type":53,"value":1136},"Operation Limits",{"type":47,"tag":56,"props":1138,"children":1139},{},[1140],{"type":53,"value":1141},"Present the tuning guidance:",{"type":47,"tag":92,"props":1143,"children":1146},{"className":1144,"code":1145,"language":53},[95],"Operation depth limit controls how deeply nested a query can be.\n\n  Router default: 100 (permissive — allows very deep queries)\n  Recommended starting point: 50\n\n  Lower values (15–25) are more secure but will reject legitimate queries\n  in schemas with deep entity relationships or nested fragments.\n  Higher values (75–100) are safer for compatibility but offer less\n  protection against depth-based abuse.\n\n  Tip: Run your router in warn_only mode first to see what depths your\n  real traffic actually uses, then tighten:\n    limits:\n      warn_only: true\n\nWhat max_depth would you like? [default: 50]\n",[1147],{"type":47,"tag":99,"props":1148,"children":1149},{"__ignoreMap":101},[1150],{"type":53,"value":1145},{"type":47,"tag":56,"props":1152,"children":1153},{},[1154,1156,1162,1163,1169,1170,1176],{"type":53,"value":1155},"The same principle applies to ",{"type":47,"tag":99,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":53,"value":1161},"max_height",{"type":53,"value":417},{"type":47,"tag":99,"props":1164,"children":1166},{"className":1165},[],[1167],{"type":53,"value":1168},"max_aliases",{"type":53,"value":446},{"type":47,"tag":99,"props":1171,"children":1173},{"className":1172},[],[1174],{"type":53,"value":1175},"max_root_fields",{"type":53,"value":454},{"type":47,"tag":499,"props":1178,"children":1179},{"id":444},[1180],{"type":53,"value":1181},"Telemetry",{"type":47,"tag":168,"props":1183,"children":1184},{},[1185,1197,1209],{"type":47,"tag":172,"props":1186,"children":1187},{},[1188,1190,1196],{"type":53,"value":1189},"OTEL collector endpoint (default: ",{"type":47,"tag":99,"props":1191,"children":1193},{"className":1192},[],[1194],{"type":53,"value":1195},"http:\u002F\u002Fotel-collector:4317",{"type":53,"value":355},{"type":47,"tag":172,"props":1198,"children":1199},{},[1200,1202,1208],{"type":53,"value":1201},"Prometheus listen port (default: ",{"type":47,"tag":99,"props":1203,"children":1205},{"className":1204},[],[1206],{"type":53,"value":1207},"9090",{"type":53,"value":355},{"type":47,"tag":172,"props":1210,"children":1211},{},[1212,1214,1220],{"type":53,"value":1213},"Trace sampling rate (default: ",{"type":47,"tag":99,"props":1215,"children":1217},{"className":1216},[],[1218],{"type":53,"value":1219},"0.1",{"type":53,"value":1221}," = 10%)",{"type":47,"tag":499,"props":1223,"children":1224},{"id":452},[1225],{"type":53,"value":1226},"Traffic Shaping",{"type":47,"tag":168,"props":1228,"children":1229},{},[1230,1235,1240],{"type":47,"tag":172,"props":1231,"children":1232},{},[1233],{"type":53,"value":1234},"Client-facing rate limit capacity (default: 1000 req\u002Fs)",{"type":47,"tag":172,"props":1236,"children":1237},{},[1238],{"type":53,"value":1239},"Router timeout (default: 60s)",{"type":47,"tag":172,"props":1241,"children":1242},{},[1243],{"type":53,"value":1244},"Subgraph timeout (default: 30s)",{"type":47,"tag":499,"props":1246,"children":1248},{"id":1247},"response-caching-v2-only-v260",[1249],{"type":53,"value":1250},"Response Caching (v2 only, v2.6.0+)",{"type":47,"tag":562,"props":1252,"children":1253},{},[1254],{"type":47,"tag":56,"props":1255,"children":1256},{},[1257,1262,1264,1270,1272,1277,1279,1285],{"type":47,"tag":65,"props":1258,"children":1259},{},[1260],{"type":53,"value":1261},"Security: data leakage risk.",{"type":53,"value":1263}," Before generating any response cache config, you MUST ask the user which types and fields return user-specific data.  Cached data defaults to shared — subgraph responses without ",{"type":47,"tag":99,"props":1265,"children":1267},{"className":1266},[],[1268],{"type":53,"value":1269},"Cache-Control: private",{"type":53,"value":1271}," are visible to all users.  User-specific subgraphs must return ",{"type":47,"tag":99,"props":1273,"children":1275},{"className":1274},[],[1276],{"type":53,"value":1269},{"type":53,"value":1278}," and have ",{"type":47,"tag":99,"props":1280,"children":1282},{"className":1281},[],[1283],{"type":53,"value":1284},"private_id",{"type":53,"value":1286}," configured on the router.",{"type":47,"tag":168,"props":1288,"children":1289},{},[1290,1301,1320,1332,1344,1349,1360],{"type":47,"tag":172,"props":1291,"children":1292},{},[1293,1294,1299],{"type":53,"value":152},{"type":47,"tag":65,"props":1295,"children":1296},{},[1297],{"type":53,"value":1298},"Which subgraphs serve user-specific data?",{"type":53,"value":1300}," (e.g., accounts, profiles, carts)",{"type":47,"tag":172,"props":1302,"children":1303},{},[1304,1305,1310,1312,1318],{"type":53,"value":152},{"type":47,"tag":65,"props":1306,"children":1307},{},[1308],{"type":53,"value":1309},"How do you identify users?",{"type":53,"value":1311}," (JWT ",{"type":47,"tag":99,"props":1313,"children":1315},{"className":1314},[],[1316],{"type":53,"value":1317},"sub",{"type":53,"value":1319}," claim, session token, API key)",{"type":47,"tag":172,"props":1321,"children":1322},{},[1323,1325,1331],{"type":53,"value":1324},"Redis URL (default: ",{"type":47,"tag":99,"props":1326,"children":1328},{"className":1327},[],[1329],{"type":53,"value":1330},"redis:\u002F\u002Flocalhost:6379",{"type":53,"value":355},{"type":47,"tag":172,"props":1333,"children":1334},{},[1335,1337,1343],{"type":53,"value":1336},"Default TTL (default: ",{"type":47,"tag":99,"props":1338,"children":1340},{"className":1339},[],[1341],{"type":53,"value":1342},"5m",{"type":53,"value":355},{"type":47,"tag":172,"props":1345,"children":1346},{},[1347],{"type":53,"value":1348},"Enable active invalidation? If yes: invalidation listen address and shared key",{"type":47,"tag":172,"props":1350,"children":1351},{},[1352,1354],{"type":53,"value":1353},"Use section template: ",{"type":47,"tag":99,"props":1355,"children":1357},{"className":1356},[],[1358],{"type":53,"value":1359},"templates\u002Fv2\u002Fsections\u002Fresponse-caching.yaml",{"type":47,"tag":172,"props":1361,"children":1362},{},[1363,1365,1371],{"type":53,"value":1364},"For security requirements, schema directives, and advanced config: ",{"type":47,"tag":99,"props":1366,"children":1368},{"className":1367},[],[1369],{"type":53,"value":1370},"references\u002Fresponse-caching.md",{"type":53,"value":1372}," (start with the Security section)",{"type":47,"tag":73,"props":1374,"children":1376},{"id":1375},"step-5-generate-config",[1377],{"type":53,"value":1378},"Step 5: Generate Config",{"type":47,"tag":1380,"props":1381,"children":1382},"ol",{},[1383,1394,1399,1404],{"type":47,"tag":172,"props":1384,"children":1385},{},[1386,1388],{"type":53,"value":1387},"Load the correct version template from ",{"type":47,"tag":99,"props":1389,"children":1391},{"className":1390},[],[1392],{"type":53,"value":1393},"templates\u002F{version}\u002F",{"type":47,"tag":172,"props":1395,"children":1396},{},[1397],{"type":53,"value":1398},"Assemble section templates for supported sectioned features, then merge base-template snippets for APQ\u002Fsubscriptions as needed",{"type":47,"tag":172,"props":1400,"children":1401},{},[1402],{"type":53,"value":1403},"Inject user-provided parameters",{"type":47,"tag":172,"props":1405,"children":1406},{},[1407],{"type":53,"value":1408},"Add a comment block at the top stating the target version",{"type":47,"tag":73,"props":1410,"children":1412},{"id":1411},"step-6-validate",[1413],{"type":53,"value":1414},"Step 6: Validate",{"type":47,"tag":56,"props":1416,"children":1417},{},[1418,1420,1427],{"type":53,"value":1419},"Run the ",{"type":47,"tag":1421,"props":1422,"children":1424},"a",{"href":1423},"validation\u002Fchecklist.md",[1425],{"type":53,"value":1426},"post-generation checklist",{"type":53,"value":90},{"type":47,"tag":168,"props":1429,"children":1431},{"className":1430},[230],[1432,1441,1450,1475,1498,1507,1516,1525],{"type":47,"tag":172,"props":1433,"children":1435},{"className":1434},[235],[1436,1439],{"type":47,"tag":238,"props":1437,"children":1438},{"disabled":240,"type":241},[],{"type":53,"value":1440}," All env vars referenced in config are documented",{"type":47,"tag":172,"props":1442,"children":1444},{"className":1443},[235],[1445,1448],{"type":47,"tag":238,"props":1446,"children":1447},{"disabled":240,"type":241},[],{"type":53,"value":1449}," CORS origins don't include wildcards (production)",{"type":47,"tag":172,"props":1451,"children":1453},{"className":1452},[235],[1454,1457,1459,1465,1467,1473],{"type":47,"tag":238,"props":1455,"children":1456},{"disabled":240,"type":241},[],{"type":53,"value":1458}," Rate limiting is on ",{"type":47,"tag":99,"props":1460,"children":1462},{"className":1461},[],[1463],{"type":53,"value":1464},"router:",{"type":53,"value":1466}," (client-facing), not only ",{"type":47,"tag":99,"props":1468,"children":1470},{"className":1469},[],[1471],{"type":53,"value":1472},"all:",{"type":53,"value":1474}," (subgraph)",{"type":47,"tag":172,"props":1476,"children":1478},{"className":1477},[235],[1479,1482,1484,1489,1491,1496],{"type":47,"tag":238,"props":1480,"children":1481},{"disabled":240,"type":241},[],{"type":53,"value":1483}," JWT uses ",{"type":47,"tag":99,"props":1485,"children":1487},{"className":1486},[],[1488],{"type":53,"value":552},{"type":53,"value":1490}," (v2) not ",{"type":47,"tag":99,"props":1492,"children":1494},{"className":1493},[],[1495],{"type":53,"value":544},{"type":53,"value":1497}," (v1), or vice versa",{"type":47,"tag":172,"props":1499,"children":1501},{"className":1500},[235],[1502,1505],{"type":47,"tag":238,"props":1503,"children":1504},{"disabled":240,"type":241},[],{"type":53,"value":1506}," If production: introspection=false, sandbox=false, subgraph_errors=false",{"type":47,"tag":172,"props":1508,"children":1510},{"className":1509},[235],[1511,1514],{"type":47,"tag":238,"props":1512,"children":1513},{"disabled":240,"type":241},[],{"type":53,"value":1515}," Health check is enabled",{"type":47,"tag":172,"props":1517,"children":1519},{"className":1518},[235],[1520,1523],{"type":47,"tag":238,"props":1521,"children":1522},{"disabled":240,"type":241},[],{"type":53,"value":1524}," Homepage is disabled (production)",{"type":47,"tag":172,"props":1526,"children":1528},{"className":1527},[235],[1529,1532,1534,1540],{"type":47,"tag":238,"props":1530,"children":1531},{"disabled":240,"type":241},[],{"type":53,"value":1533}," Run: ",{"type":47,"tag":99,"props":1535,"children":1537},{"className":1536},[],[1538],{"type":53,"value":1539},"router config validate \u003Cfile>",{"type":53,"value":1541}," if Router binary is available",{"type":47,"tag":73,"props":1543,"children":1545},{"id":1544},"required-validation-gate-always-run",[1546],{"type":53,"value":1547},"Required Validation Gate (always run)",{"type":47,"tag":56,"props":1549,"children":1550},{},[1551,1553,1558],{"type":53,"value":1552},"After generating or editing any ",{"type":47,"tag":99,"props":1554,"children":1556},{"className":1555},[],[1557],{"type":53,"value":757},{"type":53,"value":1559},", you MUST:",{"type":47,"tag":1380,"props":1561,"children":1562},{},[1563,1575,1587,1592],{"type":47,"tag":172,"props":1564,"children":1565},{},[1566,1568,1573],{"type":53,"value":1567},"Run ",{"type":47,"tag":99,"props":1569,"children":1571},{"className":1570},[],[1572],{"type":53,"value":1423},{"type":53,"value":1574}," and report pass\u002Ffail for each checklist item.",{"type":47,"tag":172,"props":1576,"children":1577},{},[1578,1579,1585],{"type":53,"value":1567},{"type":47,"tag":99,"props":1580,"children":1582},{"className":1581},[],[1583],{"type":53,"value":1584},"router config validate \u003Cpath-to-router.yaml>",{"type":53,"value":1586}," if Router CLI is available.",{"type":47,"tag":172,"props":1588,"children":1589},{},[1590],{"type":53,"value":1591},"If Router CLI is unavailable, state that explicitly and still complete the checklist.",{"type":47,"tag":172,"props":1593,"children":1594},{},[1595],{"type":53,"value":1596},"Do not present the configuration as final until validation is completed.",{"type":47,"tag":73,"props":1598,"children":1600},{"id":1599},"configuration-as-code-git-cicd",[1601],{"type":53,"value":1602},"Configuration as Code (git + CI\u002FCD)",{"type":47,"tag":56,"props":1604,"children":1605},{},[1606,1611],{"type":47,"tag":99,"props":1607,"children":1609},{"className":1608},[],[1610],{"type":53,"value":757},{"type":53,"value":1612}," is the router's contract with every request — treat it like application code, not an ops afterthought. Whenever you generate or edit config, steer the user toward this workflow:",{"type":47,"tag":168,"props":1614,"children":1615},{},[1616,1633,1658,1676,1709],{"type":47,"tag":172,"props":1617,"children":1618},{},[1619,1631],{"type":47,"tag":65,"props":1620,"children":1621},{},[1622,1624,1629],{"type":53,"value":1623},"Commit ",{"type":47,"tag":99,"props":1625,"children":1627},{"className":1626},[],[1628],{"type":53,"value":757},{"type":53,"value":1630}," to version control.",{"type":53,"value":1632}," It should live in git alongside the service, with changes reviewed via pull request. This gives you history, blame, and rollback for the most safety-critical file in the API layer.",{"type":47,"tag":172,"props":1634,"children":1635},{},[1636,1641,1643,1648,1650,1656],{"type":47,"tag":65,"props":1637,"children":1638},{},[1639],{"type":53,"value":1640},"Never commit secrets.",{"type":53,"value":1642}," Keep ",{"type":47,"tag":99,"props":1644,"children":1646},{"className":1645},[],[1647],{"type":53,"value":841},{"type":53,"value":1649},", JWKS URLs, Redis URLs, and invalidation keys out of the file — reference them with ",{"type":47,"tag":99,"props":1651,"children":1653},{"className":1652},[],[1654],{"type":53,"value":1655},"${env.*}",{"type":53,"value":1657}," expansion and inject at deploy time. The committed file should be safe to read by anyone with repo access.",{"type":47,"tag":172,"props":1659,"children":1660},{},[1661,1666,1668,1674],{"type":47,"tag":65,"props":1662,"children":1663},{},[1664],{"type":53,"value":1665},"Validate in CI.",{"type":53,"value":1667}," Run ",{"type":47,"tag":99,"props":1669,"children":1671},{"className":1670},[],[1672],{"type":53,"value":1673},"router config validate router.yaml",{"type":53,"value":1675}," on every PR so a malformed or version-mismatched config fails the build before it ships. Pin the Router version used in CI to the version you deploy.",{"type":47,"tag":172,"props":1677,"children":1678},{},[1679,1684,1686,1692,1693,1699,1701,1707],{"type":47,"tag":65,"props":1680,"children":1681},{},[1682],{"type":53,"value":1683},"Pair config changes with schema checks.",{"type":53,"value":1685}," Schema changes flow through ",{"type":47,"tag":99,"props":1687,"children":1689},{"className":1688},[],[1690],{"type":53,"value":1691},"rover subgraph check",{"type":53,"value":261},{"type":47,"tag":99,"props":1694,"children":1696},{"className":1695},[],[1697],{"type":53,"value":1698},"rover subgraph publish",{"type":53,"value":1700}," (the ",{"type":47,"tag":99,"props":1702,"children":1704},{"className":1703},[],[1705],{"type":53,"value":1706},"rover",{"type":53,"value":1708}," skill); config changes flow through this validate-in-CI gate. Both gate the same deploy.",{"type":47,"tag":172,"props":1710,"children":1711},{},[1712,1717],{"type":47,"tag":65,"props":1713,"children":1714},{},[1715],{"type":53,"value":1716},"Promote the same file across environments.",{"type":53,"value":1718}," Differences between dev and prod should be expressed through env vars, not divergent committed files, so what you reviewed is what runs.",{"type":47,"tag":56,"props":1720,"children":1721},{},[1722],{"type":53,"value":1723},"A minimal CI step (provide actual commands only if asked):",{"type":47,"tag":92,"props":1725,"children":1729},{"className":1726,"code":1727,"language":1728,"meta":101,"style":101},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# Validate router config on every pull request\n- run: router config validate router.yaml\n","yaml",[1730],{"type":47,"tag":99,"props":1731,"children":1732},{"__ignoreMap":101},[1733,1744],{"type":47,"tag":113,"props":1734,"children":1737},{"class":1735,"line":1736},"line",1,[1738],{"type":47,"tag":113,"props":1739,"children":1741},{"style":1740},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[1742],{"type":53,"value":1743},"# Validate router config on every pull request\n",{"type":47,"tag":113,"props":1745,"children":1747},{"class":1735,"line":1746},2,[1748,1754,1760,1764],{"type":47,"tag":113,"props":1749,"children":1751},{"style":1750},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[1752],{"type":53,"value":1753},"-",{"type":47,"tag":113,"props":1755,"children":1757},{"style":1756},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1758],{"type":53,"value":1759}," run",{"type":47,"tag":113,"props":1761,"children":1762},{"style":1750},[1763],{"type":53,"value":90},{"type":47,"tag":113,"props":1765,"children":1767},{"style":1766},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[1768],{"type":53,"value":1769}," router config validate router.yaml\n",{"type":47,"tag":73,"props":1771,"children":1773},{"id":1772},"step-7-conditional-next-steps-handoff",[1774],{"type":53,"value":1775},"Step 7: Conditional Next Steps Handoff",{"type":47,"tag":56,"props":1777,"children":1778},{},[1779],{"type":53,"value":1780},"After answering any Apollo Router request (config generation, edits, validation, or general Router guidance), decide whether the user already has runnable prerequisites:",{"type":47,"tag":168,"props":1782,"children":1783},{},[1784,1802],{"type":47,"tag":172,"props":1785,"children":1786},{},[1787,1789,1794,1795,1800],{"type":53,"value":1788},"GraphOS-managed path: ",{"type":47,"tag":99,"props":1790,"children":1792},{"className":1791},[],[1793],{"type":53,"value":841},{"type":53,"value":843},{"type":47,"tag":99,"props":1796,"children":1798},{"className":1797},[],[1799],{"type":53,"value":849},{"type":53,"value":1801},", or",{"type":47,"tag":172,"props":1803,"children":1804},{},[1805,1807,1813],{"type":53,"value":1806},"Local path: a composed ",{"type":47,"tag":99,"props":1808,"children":1810},{"className":1809},[],[1811],{"type":53,"value":1812},"supergraph.graphql",{"type":53,"value":1814}," plus reachable subgraphs",{"type":47,"tag":56,"props":1816,"children":1817},{},[1818],{"type":53,"value":1819},"If prerequisites are already present, do not add extra handoff text.",{"type":47,"tag":56,"props":1821,"children":1822},{},[1823,1825,1830],{"type":53,"value":1824},"If prerequisites are missing or unknown, end with a concise ",{"type":47,"tag":65,"props":1826,"children":1827},{},[1828],{"type":53,"value":1829},"Next steps",{"type":53,"value":1831}," handoff (1-3 lines max) that is skill-first and command-free:",{"type":47,"tag":1380,"props":1833,"children":1834},{},[1835,1847,1859],{"type":47,"tag":172,"props":1836,"children":1837},{},[1838,1840,1845],{"type":53,"value":1839},"Suggest the ",{"type":47,"tag":99,"props":1841,"children":1843},{"className":1842},[],[1844],{"type":53,"value":1706},{"type":53,"value":1846}," skill to compose or fetch the supergraph schema.",{"type":47,"tag":172,"props":1848,"children":1849},{},[1850,1852,1857],{"type":53,"value":1851},"Suggest continuing with ",{"type":47,"tag":99,"props":1853,"children":1855},{"className":1854},[],[1856],{"type":53,"value":4},{"type":53,"value":1858}," once the supergraph is ready to validate and run with the generated config.",{"type":47,"tag":172,"props":1860,"children":1861},{},[1862,1864,1870,1871,1877,1878,1884],{"type":53,"value":1863},"If subgraphs are missing, suggest ",{"type":47,"tag":99,"props":1865,"children":1867},{"className":1866},[],[1868],{"type":53,"value":1869},"apollo-server",{"type":53,"value":417},{"type":47,"tag":99,"props":1872,"children":1874},{"className":1873},[],[1875],{"type":53,"value":1876},"graphql-schema",{"type":53,"value":446},{"type":47,"tag":99,"props":1879,"children":1881},{"className":1880},[],[1882],{"type":53,"value":1883},"graphql-operations",{"type":53,"value":1885}," skills to scaffold and test.",{"type":47,"tag":56,"props":1887,"children":1888},{},[1889],{"type":53,"value":1890},"Do not include raw shell commands in this handoff unless the user explicitly asks for commands.",{"type":47,"tag":73,"props":1892,"children":1894},{"id":1893},"quick-start-skill-first",[1895],{"type":53,"value":1896},"Quick Start (skill-first)",{"type":47,"tag":1380,"props":1898,"children":1899},{},[1900,1919,1984],{"type":47,"tag":172,"props":1901,"children":1902},{},[1903,1905,1910,1912,1917],{"type":53,"value":1904},"Use this ",{"type":47,"tag":99,"props":1906,"children":1908},{"className":1907},[],[1909],{"type":53,"value":4},{"type":53,"value":1911}," skill to generate or refine ",{"type":47,"tag":99,"props":1913,"children":1915},{"className":1914},[],[1916],{"type":53,"value":757},{"type":53,"value":1918}," for your environment.",{"type":47,"tag":172,"props":1920,"children":1921},{},[1922,1924],{"type":53,"value":1923},"Choose a runtime path:\n",{"type":47,"tag":168,"props":1925,"children":1926},{},[1927,1946],{"type":47,"tag":172,"props":1928,"children":1929},{},[1930,1932,1937,1939,1944],{"type":53,"value":1931},"GraphOS-managed path: provide ",{"type":47,"tag":99,"props":1933,"children":1935},{"className":1934},[],[1936],{"type":53,"value":841},{"type":53,"value":1938}," and ",{"type":47,"tag":99,"props":1940,"children":1942},{"className":1941},[],[1943],{"type":53,"value":849},{"type":53,"value":1945}," (no local supergraph composition required).",{"type":47,"tag":172,"props":1947,"children":1948},{},[1949,1951,1956,1957,1962,1964,1969,1971,1976,1978,1983],{"type":53,"value":1950},"Local supergraph path: use ",{"type":47,"tag":99,"props":1952,"children":1954},{"className":1953},[],[1955],{"type":53,"value":1876},{"type":53,"value":843},{"type":47,"tag":99,"props":1958,"children":1960},{"className":1959},[],[1961],{"type":53,"value":1869},{"type":53,"value":1963}," to define\u002Frun subgraphs, then use ",{"type":47,"tag":99,"props":1965,"children":1967},{"className":1966},[],[1968],{"type":53,"value":1883},{"type":53,"value":1970}," for smoke tests, then use the ",{"type":47,"tag":99,"props":1972,"children":1974},{"className":1973},[],[1975],{"type":53,"value":1706},{"type":53,"value":1977}," skill to compose or fetch ",{"type":47,"tag":99,"props":1979,"children":1981},{"className":1980},[],[1982],{"type":53,"value":1812},{"type":53,"value":454},{"type":47,"tag":172,"props":1985,"children":1986},{},[1987,1988,1993,1995,2000],{"type":53,"value":1904},{"type":47,"tag":99,"props":1989,"children":1991},{"className":1990},[],[1992],{"type":53,"value":4},{"type":53,"value":1994}," skill to validate readiness (",{"type":47,"tag":99,"props":1996,"children":1998},{"className":1997},[],[1999],{"type":53,"value":1423},{"type":53,"value":2001},") and walk through runtime startup inputs.",{"type":47,"tag":56,"props":2003,"children":2004},{},[2005,2007,2013],{"type":53,"value":2006},"Default endpoint remains ",{"type":47,"tag":99,"props":2008,"children":2010},{"className":2009},[],[2011],{"type":53,"value":2012},"http:\u002F\u002Flocalhost:4000",{"type":53,"value":2014}," when using standard Router listen defaults.",{"type":47,"tag":56,"props":2016,"children":2017},{},[2018],{"type":53,"value":2019},"If the user asks for executable shell commands, provide them on request. Otherwise keep Quick Start guidance skill-oriented.",{"type":47,"tag":73,"props":2021,"children":2023},{"id":2022},"running-modes",[2024],{"type":53,"value":2025},"Running Modes",{"type":47,"tag":865,"props":2027,"children":2028},{},[2029,2050],{"type":47,"tag":869,"props":2030,"children":2031},{},[2032],{"type":47,"tag":873,"props":2033,"children":2034},{},[2035,2040,2045],{"type":47,"tag":877,"props":2036,"children":2037},{},[2038],{"type":53,"value":2039},"Mode",{"type":47,"tag":877,"props":2041,"children":2042},{},[2043],{"type":53,"value":2044},"Command",{"type":47,"tag":877,"props":2046,"children":2047},{},[2048],{"type":53,"value":2049},"Use Case",{"type":47,"tag":893,"props":2051,"children":2052},{},[2053,2075,2097,2118],{"type":47,"tag":873,"props":2054,"children":2055},{},[2056,2061,2070],{"type":47,"tag":900,"props":2057,"children":2058},{},[2059],{"type":53,"value":2060},"Local schema",{"type":47,"tag":900,"props":2062,"children":2063},{},[2064],{"type":47,"tag":99,"props":2065,"children":2067},{"className":2066},[],[2068],{"type":53,"value":2069},"router --supergraph .\u002Fschema.graphql",{"type":47,"tag":900,"props":2071,"children":2072},{},[2073],{"type":53,"value":2074},"Development, CI\u002FCD",{"type":47,"tag":873,"props":2076,"children":2077},{},[2078,2083,2092],{"type":47,"tag":900,"props":2079,"children":2080},{},[2081],{"type":53,"value":2082},"GraphOS managed",{"type":47,"tag":900,"props":2084,"children":2085},{},[2086],{"type":47,"tag":99,"props":2087,"children":2089},{"className":2088},[],[2090],{"type":53,"value":2091},"APOLLO_KEY=... APOLLO_GRAPH_REF=my-graph@prod router",{"type":47,"tag":900,"props":2093,"children":2094},{},[2095],{"type":53,"value":2096},"Production with auto-updates",{"type":47,"tag":873,"props":2098,"children":2099},{},[2100,2104,2113],{"type":47,"tag":900,"props":2101,"children":2102},{},[2103],{"type":53,"value":164},{"type":47,"tag":900,"props":2105,"children":2106},{},[2107],{"type":47,"tag":99,"props":2108,"children":2110},{"className":2109},[],[2111],{"type":53,"value":2112},"router --dev --supergraph .\u002Fschema.graphql",{"type":47,"tag":900,"props":2114,"children":2115},{},[2116],{"type":53,"value":2117},"Local development",{"type":47,"tag":873,"props":2119,"children":2120},{},[2121,2126,2135],{"type":47,"tag":900,"props":2122,"children":2123},{},[2124],{"type":53,"value":2125},"Hot reload",{"type":47,"tag":900,"props":2127,"children":2128},{},[2129],{"type":47,"tag":99,"props":2130,"children":2132},{"className":2131},[],[2133],{"type":53,"value":2134},"router --hot-reload --supergraph .\u002Fschema.graphql",{"type":47,"tag":900,"props":2136,"children":2137},{},[2138],{"type":53,"value":2139},"Schema changes without restart",{"type":47,"tag":73,"props":2141,"children":2143},{"id":2142},"environment-variables",[2144],{"type":53,"value":2145},"Environment Variables",{"type":47,"tag":865,"props":2147,"children":2148},{},[2149,2165],{"type":47,"tag":869,"props":2150,"children":2151},{},[2152],{"type":47,"tag":873,"props":2153,"children":2154},{},[2155,2160],{"type":47,"tag":877,"props":2156,"children":2157},{},[2158],{"type":53,"value":2159},"Variable",{"type":47,"tag":877,"props":2161,"children":2162},{},[2163],{"type":53,"value":2164},"Description",{"type":47,"tag":893,"props":2166,"children":2167},{},[2168,2184,2207,2229,2246,2263],{"type":47,"tag":873,"props":2169,"children":2170},{},[2171,2179],{"type":47,"tag":900,"props":2172,"children":2173},{},[2174],{"type":47,"tag":99,"props":2175,"children":2177},{"className":2176},[],[2178],{"type":53,"value":841},{"type":47,"tag":900,"props":2180,"children":2181},{},[2182],{"type":53,"value":2183},"API key for GraphOS",{"type":47,"tag":873,"props":2185,"children":2186},{},[2187,2195],{"type":47,"tag":900,"props":2188,"children":2189},{},[2190],{"type":47,"tag":99,"props":2191,"children":2193},{"className":2192},[],[2194],{"type":53,"value":849},{"type":47,"tag":900,"props":2196,"children":2197},{},[2198,2200,2206],{"type":53,"value":2199},"Graph reference (",{"type":47,"tag":99,"props":2201,"children":2203},{"className":2202},[],[2204],{"type":53,"value":2205},"graph-id@variant",{"type":53,"value":355},{"type":47,"tag":873,"props":2208,"children":2209},{},[2210,2219],{"type":47,"tag":900,"props":2211,"children":2212},{},[2213],{"type":47,"tag":99,"props":2214,"children":2216},{"className":2215},[],[2217],{"type":53,"value":2218},"APOLLO_ROUTER_CONFIG_PATH",{"type":47,"tag":900,"props":2220,"children":2221},{},[2222,2224],{"type":53,"value":2223},"Path to ",{"type":47,"tag":99,"props":2225,"children":2227},{"className":2226},[],[2228],{"type":53,"value":757},{"type":47,"tag":873,"props":2230,"children":2231},{},[2232,2241],{"type":47,"tag":900,"props":2233,"children":2234},{},[2235],{"type":47,"tag":99,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":53,"value":2240},"APOLLO_ROUTER_SUPERGRAPH_PATH",{"type":47,"tag":900,"props":2242,"children":2243},{},[2244],{"type":53,"value":2245},"Path to supergraph schema",{"type":47,"tag":873,"props":2247,"children":2248},{},[2249,2258],{"type":47,"tag":900,"props":2250,"children":2251},{},[2252],{"type":47,"tag":99,"props":2253,"children":2255},{"className":2254},[],[2256],{"type":53,"value":2257},"APOLLO_ROUTER_LOG",{"type":47,"tag":900,"props":2259,"children":2260},{},[2261],{"type":53,"value":2262},"Log level (off, error, warn, info, debug, trace)",{"type":47,"tag":873,"props":2264,"children":2265},{},[2266,2275],{"type":47,"tag":900,"props":2267,"children":2268},{},[2269],{"type":47,"tag":99,"props":2270,"children":2272},{"className":2271},[],[2273],{"type":53,"value":2274},"APOLLO_ROUTER_LISTEN_ADDRESS",{"type":47,"tag":900,"props":2276,"children":2277},{},[2278],{"type":53,"value":2279},"Override listen address",{"type":47,"tag":73,"props":2281,"children":2283},{"id":2282},"reference-files",[2284],{"type":53,"value":2285},"Reference Files",{"type":47,"tag":168,"props":2287,"children":2288},{},[2289,2299,2310,2321,2331,2342,2352,2363,2374],{"type":47,"tag":172,"props":2290,"children":2291},{},[2292,2297],{"type":47,"tag":1421,"props":2293,"children":2294},{"href":772},[2295],{"type":53,"value":2296},"Configuration",{"type":53,"value":2298}," — YAML configuration reference",{"type":47,"tag":172,"props":2300,"children":2301},{},[2302,2308],{"type":47,"tag":1421,"props":2303,"children":2305},{"href":2304},"references\u002Fheaders.md",[2306],{"type":53,"value":2307},"Headers",{"type":53,"value":2309}," — Header propagation and manipulation",{"type":47,"tag":172,"props":2311,"children":2312},{},[2313,2319],{"type":47,"tag":1421,"props":2314,"children":2316},{"href":2315},"references\u002Fplugins.md",[2317],{"type":53,"value":2318},"Plugins",{"type":53,"value":2320}," — Rhai scripts and coprocessors",{"type":47,"tag":172,"props":2322,"children":2323},{},[2324,2329],{"type":47,"tag":1421,"props":2325,"children":2327},{"href":2326},"references\u002Ftelemetry.md",[2328],{"type":53,"value":1181},{"type":53,"value":2330}," — Tracing, metrics, and logging",{"type":47,"tag":172,"props":2332,"children":2333},{},[2334,2340],{"type":47,"tag":1421,"props":2335,"children":2337},{"href":2336},"references\u002Fconnectors.md",[2338],{"type":53,"value":2339},"Connectors",{"type":53,"value":2341}," — Router v2 connectors configuration",{"type":47,"tag":172,"props":2343,"children":2344},{},[2345,2350],{"type":47,"tag":1421,"props":2346,"children":2347},{"href":1370},[2348],{"type":53,"value":2349},"Response Caching",{"type":53,"value":2351}," — Entity\u002Froot-field caching, invalidation, and observability (v2 only)",{"type":47,"tag":172,"props":2353,"children":2354},{},[2355,2361],{"type":47,"tag":1421,"props":2356,"children":2358},{"href":2357},"references\u002Ftroubleshooting.md",[2359],{"type":53,"value":2360},"Troubleshooting",{"type":53,"value":2362}," — Common issues and solutions",{"type":47,"tag":172,"props":2364,"children":2365},{},[2366,2372],{"type":47,"tag":1421,"props":2367,"children":2369},{"href":2368},"divergence-map.md",[2370],{"type":53,"value":2371},"Divergence Map",{"type":53,"value":2373}," — v1 ↔ v2 config differences",{"type":47,"tag":172,"props":2375,"children":2376},{},[2377,2382],{"type":47,"tag":1421,"props":2378,"children":2379},{"href":1423},[2380],{"type":53,"value":2381},"Validation Checklist",{"type":53,"value":2383}," — Post-generation checks",{"type":47,"tag":73,"props":2385,"children":2387},{"id":2386},"cli-reference",[2388],{"type":53,"value":2389},"CLI Reference",{"type":47,"tag":92,"props":2391,"children":2394},{"className":2392,"code":2393,"language":53},[95],"router [OPTIONS]\n\nOptions:\n  -s, --supergraph \u003CPATH>    Path to supergraph schema file\n  -c, --config \u003CPATH>        Path to router.yaml configuration\n      --dev                  Enable development mode\n      --hot-reload           Watch for schema changes\n      --log \u003CLEVEL>          Log level (default: info)\n      --listen \u003CADDRESS>     Override listen address\n  -V, --version              Print version\n  -h, --help                 Print help\n",[2395],{"type":47,"tag":99,"props":2396,"children":2397},{"__ignoreMap":101},[2398],{"type":53,"value":2393},{"type":47,"tag":73,"props":2400,"children":2402},{"id":2401},"ground-rules",[2403],{"type":53,"value":2404},"Ground Rules",{"type":47,"tag":168,"props":2406,"children":2407},{},[2408,2413,2418,2423,2436,2441,2446,2459,2471,2484,2489,2494,2507,2520,2532,2543,2548,2553,2558,2563,2568,2580,2592,2604,2615,2628,2633,2638,2664,2669,2690,2710,2729,2748,2773,2791,2822,2833,2846,2863,2875,2902],{"type":47,"tag":172,"props":2409,"children":2410},{},[2411],{"type":53,"value":2412},"ALWAYS determine the target Router version (v1 or v2) before generating config",{"type":47,"tag":172,"props":2414,"children":2415},{},[2416],{"type":53,"value":2417},"DEFAULT to v2 for new projects",{"type":47,"tag":172,"props":2419,"children":2420},{},[2421],{"type":53,"value":2422},"ALWAYS include a comment block at top of generated config stating the target version",{"type":47,"tag":172,"props":2424,"children":2425},{},[2426,2428,2434],{"type":53,"value":2427},"ALWAYS use ",{"type":47,"tag":99,"props":2429,"children":2431},{"className":2430},[],[2432],{"type":53,"value":2433},"--dev",{"type":53,"value":2435}," mode for local development (enables introspection and sandbox)",{"type":47,"tag":172,"props":2437,"children":2438},{},[2439],{"type":53,"value":2440},"ALWAYS disable introspection, sandbox, and homepage in production",{"type":47,"tag":172,"props":2442,"children":2443},{},[2444],{"type":53,"value":2445},"PREFER GraphOS managed mode for production (automatic updates, metrics)",{"type":47,"tag":172,"props":2447,"children":2448},{},[2449,2451,2457],{"type":53,"value":2450},"USE ",{"type":47,"tag":99,"props":2452,"children":2454},{"className":2453},[],[2455],{"type":53,"value":2456},"--hot-reload",{"type":53,"value":2458}," for local development with file-based schemas",{"type":47,"tag":172,"props":2460,"children":2461},{},[2462,2464,2469],{"type":53,"value":2463},"NEVER expose ",{"type":47,"tag":99,"props":2465,"children":2467},{"className":2466},[],[2468],{"type":53,"value":841},{"type":53,"value":2470}," in logs or version control",{"type":47,"tag":172,"props":2472,"children":2473},{},[2474,2476,2482],{"type":53,"value":2475},"USE environment variables (",{"type":47,"tag":99,"props":2477,"children":2479},{"className":2478},[],[2480],{"type":53,"value":2481},"${env.VAR}",{"type":53,"value":2483},") for all secrets and sensitive config",{"type":47,"tag":172,"props":2485,"children":2486},{},[2487],{"type":53,"value":2488},"PREFER YAML configuration over command-line arguments for complex setups",{"type":47,"tag":172,"props":2490,"children":2491},{},[2492],{"type":53,"value":2493},"TEST configuration changes locally before deploying to production",{"type":47,"tag":172,"props":2495,"children":2496},{},[2497,2499,2505],{"type":53,"value":2498},"WARN if user enables ",{"type":47,"tag":99,"props":2500,"children":2502},{"className":2501},[],[2503],{"type":53,"value":2504},"allow_any_origin",{"type":53,"value":2506}," or wildcard CORS in production",{"type":47,"tag":172,"props":2508,"children":2509},{},[2510,2512,2518],{"type":53,"value":2511},"RECOMMEND ",{"type":47,"tag":99,"props":2513,"children":2515},{"className":2514},[],[2516],{"type":53,"value":2517},"router config upgrade router.yaml",{"type":53,"value":2519}," for v1 → v2 migration instead of regenerating from scratch",{"type":47,"tag":172,"props":2521,"children":2522},{},[2523,2525,2530],{"type":53,"value":2524},"MUST run ",{"type":47,"tag":99,"props":2526,"children":2528},{"className":2527},[],[2529],{"type":53,"value":1423},{"type":53,"value":2531}," after every router config generation or edit",{"type":47,"tag":172,"props":2533,"children":2534},{},[2535,2536,2541],{"type":53,"value":2524},{"type":47,"tag":99,"props":2537,"children":2539},{"className":2538},[],[2540],{"type":53,"value":1539},{"type":53,"value":2542}," when Router CLI is available",{"type":47,"tag":172,"props":2544,"children":2545},{},[2546],{"type":53,"value":2547},"MUST report when CLI validation could not run (for example, Router binary missing)",{"type":47,"tag":172,"props":2549,"children":2550},{},[2551],{"type":53,"value":2552},"MUST append a brief conditional handoff when runtime prerequisites are missing or unknown",{"type":47,"tag":172,"props":2554,"children":2555},{},[2556],{"type":53,"value":2557},"MUST make this handoff skill-first and avoid raw shell commands unless the user explicitly requests commands",{"type":47,"tag":172,"props":2559,"children":2560},{},[2561],{"type":53,"value":2562},"MUST keep Quick Start guidance skill-first and command-free unless the user explicitly requests commands",{"type":47,"tag":172,"props":2564,"children":2565},{},[2566],{"type":53,"value":2567},"MUST state that Rover is required only for the local supergraph path; GraphOS-managed runtime does not require local Rover composition",{"type":47,"tag":172,"props":2569,"children":2570},{},[2571,2572,2578],{"type":53,"value":2450},{"type":47,"tag":99,"props":2573,"children":2575},{"className":2574},[],[2576],{"type":53,"value":2577},"max_depth: 50",{"type":53,"value":2579}," as the default starting point, not 15 (too aggressive) or 100 (too permissive)",{"type":47,"tag":172,"props":2581,"children":2582},{},[2583,2584,2590],{"type":53,"value":2511},{"type":47,"tag":99,"props":2585,"children":2587},{"className":2586},[],[2588],{"type":53,"value":2589},"warn_only: true",{"type":53,"value":2591}," for initial limits rollout to observe real traffic before enforcing",{"type":47,"tag":172,"props":2593,"children":2594},{},[2595,2597,2602],{"type":53,"value":2596},"ONLY offer Response Caching when ",{"type":47,"tag":99,"props":2598,"children":2600},{"className":2599},[],[2601],{"type":53,"value":496},{"type":53,"value":2603}," (requires v2.6.0+)",{"type":47,"tag":172,"props":2605,"children":2606},{},[2607,2608,2613],{"type":53,"value":2427},{"type":47,"tag":99,"props":2609,"children":2611},{"className":2610},[],[2612],{"type":53,"value":1655},{"type":53,"value":2614}," for Redis URLs, passwords, and invalidation shared keys",{"type":47,"tag":172,"props":2616,"children":2617},{},[2618,2620,2626],{"type":53,"value":2619},"NEVER enable ",{"type":47,"tag":99,"props":2621,"children":2623},{"className":2622},[],[2624],{"type":53,"value":2625},"response_cache.debug: true",{"type":53,"value":2627}," in production config",{"type":47,"tag":172,"props":2629,"children":2630},{},[2631],{"type":53,"value":2632},"RECOMMEND combining Cache-Control headers (passive TTL) with @cacheTag (active invalidation) for production",{"type":47,"tag":172,"props":2634,"children":2635},{},[2636],{"type":53,"value":2637},"ALWAYS ask which fields return user-specific data before generating response cache config — never assume all data is safe to cache as shared",{"type":47,"tag":172,"props":2639,"children":2640},{},[2641,2643,2648,2650,2655,2656,2662],{"type":53,"value":2642},"ALWAYS configure ",{"type":47,"tag":99,"props":2644,"children":2646},{"className":2645},[],[2647],{"type":53,"value":1284},{"type":53,"value":2649}," for subgraphs that serve user-specific data, and ensure those subgraphs return ",{"type":47,"tag":99,"props":2651,"children":2653},{"className":2652},[],[2654],{"type":53,"value":1269},{"type":53,"value":1017},{"type":47,"tag":99,"props":2657,"children":2659},{"className":2658},[],[2660],{"type":53,"value":2661},"@cacheControl(scope: PRIVATE)",{"type":53,"value":2663}," in Apollo Server, or by setting the header directly in other frameworks)",{"type":47,"tag":172,"props":2665,"children":2666},{},[2667],{"type":53,"value":2668},"NEVER generate response cache config without addressing private data — if the user says \"no user-specific data\", confirm explicitly before proceeding",{"type":47,"tag":172,"props":2670,"children":2671},{},[2672,2674,2680,2682,2688],{"type":53,"value":2673},"ALWAYS bind the invalidation endpoint to ",{"type":47,"tag":99,"props":2675,"children":2677},{"className":2676},[],[2678],{"type":53,"value":2679},"127.0.0.1",{"type":53,"value":2681},", NEVER ",{"type":47,"tag":99,"props":2683,"children":2685},{"className":2684},[],[2686],{"type":53,"value":2687},"0.0.0.0",{"type":53,"value":2689}," in production",{"type":47,"tag":172,"props":2691,"children":2692},{},[2693,2695,2700,2702,2708],{"type":53,"value":2694},"NEVER conflate APQ with persisted-query safelisting — APQ (",{"type":47,"tag":99,"props":2696,"children":2698},{"className":2697},[],[2699],{"type":53,"value":799},{"type":53,"value":2701},") is a bandwidth optimization with no security value; safelisting (",{"type":47,"tag":99,"props":2703,"children":2705},{"className":2704},[],[2706],{"type":53,"value":2707},"persisted_queries.safelist",{"type":53,"value":2709},") is the operation allowlist. If a user asks to \"lock down which queries can run\", point them to safelisting, not APQ",{"type":47,"tag":172,"props":2711,"children":2712},{},[2713,2715,2720,2722,2727],{"type":53,"value":2714},"ALWAYS disable APQ (",{"type":47,"tag":99,"props":2716,"children":2718},{"className":2717},[],[2719],{"type":53,"value":1049},{"type":53,"value":2721},") when enabling ",{"type":47,"tag":99,"props":2723,"children":2725},{"className":2724},[],[2726],{"type":53,"value":2707},{"type":53,"value":2728}," — they are mutually exclusive",{"type":47,"tag":172,"props":2730,"children":2731},{},[2732,2734,2740,2742],{"type":53,"value":2733},"RECOMMEND starting persisted queries in audit mode (",{"type":47,"tag":99,"props":2735,"children":2737},{"className":2736},[],[2738],{"type":53,"value":2739},"log_unknown: true",{"type":53,"value":2741},") to confirm all clients are registered before turning on ",{"type":47,"tag":99,"props":2743,"children":2745},{"className":2744},[],[2746],{"type":53,"value":2747},"safelist.enabled",{"type":47,"tag":172,"props":2749,"children":2750},{},[2751,2753,2758,2759,2764,2766,2771],{"type":53,"value":2752},"STATE that persisted-query safelisting requires a GraphOS-connected router (PQL fetched via ",{"type":47,"tag":99,"props":2754,"children":2756},{"className":2755},[],[2757],{"type":53,"value":841},{"type":53,"value":843},{"type":47,"tag":99,"props":2760,"children":2762},{"className":2761},[],[2763],{"type":53,"value":849},{"type":53,"value":2765},", or ",{"type":47,"tag":99,"props":2767,"children":2769},{"className":2768},[],[2770],{"type":53,"value":1005},{"type":53,"value":2772}," for offline licenses)",{"type":47,"tag":172,"props":2774,"children":2775},{},[2776,2777,2782,2784,2789],{"type":53,"value":2450},{"type":47,"tag":99,"props":2778,"children":2780},{"className":2779},[],[2781],{"type":53,"value":1062},{"type":53,"value":2783}," (GA, v1.32.0+ and all v2), NOT ",{"type":47,"tag":99,"props":2785,"children":2787},{"className":2786},[],[2788],{"type":53,"value":1070},{"type":53,"value":2790}," (v1.25.0–v1.32.0)",{"type":47,"tag":172,"props":2792,"children":2793},{},[2794,2796,2801,2803,2808,2809,2814,2815,2820],{"type":53,"value":2795},"TREAT global ",{"type":47,"tag":99,"props":2797,"children":2799},{"className":2798},[],[2800],{"type":53,"value":601},{"type":53,"value":2802}," and declarative directives as different layers: the former gates the whole request, the latter (",{"type":47,"tag":99,"props":2804,"children":2806},{"className":2805},[],[2807],{"type":53,"value":259},{"type":53,"value":261},{"type":47,"tag":99,"props":2810,"children":2812},{"className":2811},[],[2813],{"type":53,"value":267},{"type":53,"value":261},{"type":47,"tag":99,"props":2816,"children":2818},{"className":2817},[],[2819],{"type":53,"value":274},{"type":53,"value":2821},") does field- and type-level filtering",{"type":47,"tag":172,"props":2823,"children":2824},{},[2825,2827,2832],{"type":53,"value":2826},"STATE that declarative authorization directives require a GraphOS-connected router (v1.29.1+; Developer\u002FStandard plans need v2.6.0+) and a claims source (JWT auth or a coprocessor populating ",{"type":47,"tag":99,"props":2828,"children":2830},{"className":2829},[],[2831],{"type":53,"value":658},{"type":53,"value":355},{"type":47,"tag":172,"props":2834,"children":2835},{},[2836,2838,2844],{"type":53,"value":2837},"NOTE that authorization directives are ENABLED BY DEFAULT — ",{"type":47,"tag":99,"props":2839,"children":2841},{"className":2840},[],[2842],{"type":53,"value":2843},"authorization.directives.enabled: false",{"type":53,"value":2845}," only turns them off; never imply config is required to \"turn them on\"",{"type":47,"tag":172,"props":2847,"children":2848},{},[2849,2851,2856,2858],{"type":53,"value":2850},"STATE that ",{"type":47,"tag":99,"props":2852,"children":2854},{"className":2853},[],[2855],{"type":53,"value":274},{"type":53,"value":2857}," additionally requires a Rhai script or coprocessor at the Supergraph stage to evaluate ",{"type":47,"tag":99,"props":2859,"children":2861},{"className":2860},[],[2862],{"type":53,"value":688},{"type":47,"tag":172,"props":2864,"children":2865},{},[2866,2868,2873],{"type":53,"value":2867},"PLACE authorization directives in subgraph schemas, NEVER in ",{"type":47,"tag":99,"props":2869,"children":2871},{"className":2870},[],[2872],{"type":53,"value":757},{"type":53,"value":2874}," — router config only enables\u002Fdisables the feature",{"type":47,"tag":172,"props":2876,"children":2877},{},[2878,2880,2885,2887,2893,2895,2900],{"type":53,"value":2879},"RECOMMEND committing ",{"type":47,"tag":99,"props":2881,"children":2883},{"className":2882},[],[2884],{"type":53,"value":757},{"type":53,"value":2886}," to version control and running ",{"type":47,"tag":99,"props":2888,"children":2890},{"className":2889},[],[2891],{"type":53,"value":2892},"router config validate",{"type":53,"value":2894}," in CI on every PR, with all secrets referenced via ",{"type":47,"tag":99,"props":2896,"children":2898},{"className":2897},[],[2899],{"type":53,"value":1655},{"type":53,"value":2901}," and injected at deploy time",{"type":47,"tag":172,"props":2903,"children":2904},{},[2905,2907,2912,2914,2919],{"type":53,"value":2906},"NEVER commit secrets (",{"type":47,"tag":99,"props":2908,"children":2910},{"className":2909},[],[2911],{"type":53,"value":841},{"type":53,"value":2913},", JWKS\u002FRedis URLs, invalidation keys) to the config file; the committed ",{"type":47,"tag":99,"props":2915,"children":2917},{"className":2916},[],[2918],{"type":53,"value":757},{"type":53,"value":2920}," must be safe to share with anyone holding repo access",{"type":47,"tag":2922,"props":2923,"children":2924},"style",{},[2925],{"type":53,"value":2926},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":2928,"total":3026},[2929,2944,2959,2970,2991,3006,3019],{"slug":2930,"name":2930,"fn":2931,"description":2932,"org":2933,"tags":2934,"stars":24,"repoUrl":25,"updatedAt":2943},"apollo-client","build React apps with Apollo Client","Guide for building React applications with Apollo Client 4.x. Use this skill when: (1) setting up Apollo Client in a React project, (2) writing GraphQL queries or mutations with hooks, (3) configuring caching or cache policies, (4) managing local state with reactive variables, (5) troubleshooting Apollo Client errors or performance issues.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2935,2936,2939,2940],{"name":9,"slug":8,"type":16},{"name":2937,"slug":2938,"type":16},"Frontend","frontend",{"name":14,"slug":15,"type":16},{"name":2941,"slug":2942,"type":16},"React","react","2026-04-06T18:01:12.268638",{"slug":2945,"name":2945,"fn":2946,"description":2947,"org":2948,"tags":2949,"stars":24,"repoUrl":25,"updatedAt":2958},"apollo-connectors","integrate REST APIs with Apollo Connectors","Guide for integrating REST APIs into GraphQL supergraphs using Apollo Connectors with @source and @connect directives. Use this skill when the user: (1) mentions \"connectors\", \"Apollo Connectors\", or \"REST Connector\", (2) wants to integrate a REST API into GraphQL, (3) references @source or @connect directives, (4) works with files containing \"# Note to AI Friends: This is an Apollo Connectors schema\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2950,2953,2954,2955],{"name":2951,"slug":2952,"type":16},"API Development","api-development",{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":2956,"slug":2957,"type":16},"REST API","rest-api","2026-04-06T18:01:23.758345",{"slug":2960,"name":2960,"fn":2961,"description":2962,"org":2963,"tags":2964,"stars":24,"repoUrl":25,"updatedAt":2969},"apollo-federation","author Apollo Federation subgraph schemas","Guide for authoring Apollo Federation subgraph schemas. Use this skill when: (1) creating new subgraph schemas for a federated supergraph, (2) defining or modifying entities with @key, (3) sharing types\u002Ffields across subgraphs with @shareable, (4) working with federation directives (@external, @requires, @provides, @override, @inaccessible), (5) troubleshooting composition errors, (6) any task involving federation schema design patterns.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2965,2966,2967,2968],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},"2026-07-30T05:31:51.648593",{"slug":2971,"name":2971,"fn":2972,"description":2973,"org":2974,"tags":2975,"stars":24,"repoUrl":25,"updatedAt":2990},"apollo-ios","build Apple apps with Apollo iOS","Guide for building Apple-platform applications with Apollo iOS, the strongly-typed GraphQL client for Swift. Use this skill when: (1) adding Apollo iOS to a Swift Package Manager or Xcode project, (2) configuring `apollo-codegen-config.json` and running code generation, (3) configuring an `ApolloClient` with auth, interceptors, and caching, (4) writing queries, mutations, or subscriptions from SwiftUI views, (5) writing tests against generated operation mocks.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2976,2977,2978,2981,2984,2987],{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":2979,"slug":2980,"type":16},"iOS","ios",{"name":2982,"slug":2983,"type":16},"Mobile","mobile",{"name":2985,"slug":2986,"type":16},"Swift","swift",{"name":2988,"slug":2989,"type":16},"Xcode","xcode","2026-04-29T05:35:21.329969",{"slug":2992,"name":2992,"fn":2993,"description":2994,"org":2995,"tags":2996,"stars":24,"repoUrl":25,"updatedAt":3005},"apollo-kotlin","build Kotlin apps with Apollo GraphQL","Guide for building applications with Apollo Kotlin, the GraphQL client library for Android and Kotlin. Use this skill when: (1) setting up Apollo Kotlin in a Gradle project for Android, Kotlin\u002FJVM, or KMP, (2) configuring schema download and codegen for GraphQL services, (3) configuring an `ApolloClient` with auth, interceptors, and caching, (4) writing queries, mutations, or subscriptions,\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2997,3000,3001,3002],{"name":2998,"slug":2999,"type":16},"Android","android",{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3003,"slug":3004,"type":16},"Kotlin","kotlin","2026-04-06T18:01:15.005978",{"slug":3007,"name":3007,"fn":3008,"description":3009,"org":3010,"tags":3011,"stars":24,"repoUrl":25,"updatedAt":3018},"apollo-mcp-server","connect MCP agents to GraphQL APIs","Guide for using Apollo MCP Server to connect AI agents with GraphQL APIs. Use this skill when: (1) setting up or configuring Apollo MCP Server, (2) defining MCP tools from GraphQL operations, (3) using introspection tools (introspect, search, validate, execute), (4) troubleshooting MCP server connectivity or tool execution issues.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3012,3013,3014,3015],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3016,"slug":3017,"type":16},"MCP","mcp","2026-04-06T18:01:20.578589",{"slug":4,"name":4,"fn":5,"description":6,"org":3020,"tags":3021,"stars":24,"repoUrl":25,"updatedAt":26},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3022,3023,3024,3025],{"name":9,"slug":8,"type":16},{"name":18,"slug":19,"type":16},{"name":22,"slug":23,"type":16},{"name":14,"slug":15,"type":16},14,{"items":3028,"total":3140},[3029,3036,3043,3050,3059,3066,3073,3080,3095,3110,3119,3129],{"slug":2930,"name":2930,"fn":2931,"description":2932,"org":3030,"tags":3031,"stars":24,"repoUrl":25,"updatedAt":2943},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3032,3033,3034,3035],{"name":9,"slug":8,"type":16},{"name":2937,"slug":2938,"type":16},{"name":14,"slug":15,"type":16},{"name":2941,"slug":2942,"type":16},{"slug":2945,"name":2945,"fn":2946,"description":2947,"org":3037,"tags":3038,"stars":24,"repoUrl":25,"updatedAt":2958},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3039,3040,3041,3042],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":2956,"slug":2957,"type":16},{"slug":2960,"name":2960,"fn":2961,"description":2962,"org":3044,"tags":3045,"stars":24,"repoUrl":25,"updatedAt":2969},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3046,3047,3048,3049],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},{"slug":2971,"name":2971,"fn":2972,"description":2973,"org":3051,"tags":3052,"stars":24,"repoUrl":25,"updatedAt":2990},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3053,3054,3055,3056,3057,3058],{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":2979,"slug":2980,"type":16},{"name":2982,"slug":2983,"type":16},{"name":2985,"slug":2986,"type":16},{"name":2988,"slug":2989,"type":16},{"slug":2992,"name":2992,"fn":2993,"description":2994,"org":3060,"tags":3061,"stars":24,"repoUrl":25,"updatedAt":3005},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3062,3063,3064,3065],{"name":2998,"slug":2999,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3003,"slug":3004,"type":16},{"slug":3007,"name":3007,"fn":3008,"description":3009,"org":3067,"tags":3068,"stars":24,"repoUrl":25,"updatedAt":3018},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3069,3070,3071,3072],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3016,"slug":3017,"type":16},{"slug":4,"name":4,"fn":5,"description":6,"org":3074,"tags":3075,"stars":24,"repoUrl":25,"updatedAt":26},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3076,3077,3078,3079],{"name":9,"slug":8,"type":16},{"name":18,"slug":19,"type":16},{"name":22,"slug":23,"type":16},{"name":14,"slug":15,"type":16},{"slug":3081,"name":3081,"fn":3082,"description":3083,"org":3084,"tags":3085,"stars":24,"repoUrl":25,"updatedAt":3094},"apollo-router-plugin-creator","write Apollo Router Rust plugins","Guide for writing Apollo Router native Rust plugins. Use this skill when: (1) users want to create a new router plugin, (2) users want to add service hooks (router_service, supergraph_service, execution_service, subgraph_service), (3) users want to modify an existing router plugin, (4) users need to understand router plugin patterns or the request lifecycle. (5) triggers on requests like \"create a new plugin\", \"add a router plugin\", \"modify the X plugin\", or \"add subgraph_service hook\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3086,3087,3088,3091],{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3089,"slug":3090,"type":16},"Plugin Development","plugin-development",{"name":3092,"slug":3093,"type":16},"Rust","rust","2026-04-06T18:01:27.176974",{"slug":1869,"name":1869,"fn":3096,"description":3097,"org":3098,"tags":3099,"stars":24,"repoUrl":25,"updatedAt":3109},"build GraphQL servers with Apollo Server","Guide for building GraphQL servers with Apollo Server 5.x. Use this skill when: (1) setting up a new Apollo Server project, (2) writing resolvers or defining GraphQL schemas, (3) implementing authentication or authorization, (4) creating plugins or custom data sources, (5) troubleshooting Apollo Server errors or performance issues.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3100,3101,3102,3103,3106],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},{"name":3104,"slug":3105,"type":16},"Node.js","nodejs",{"name":3107,"slug":3108,"type":16},"TypeScript","typescript","2026-04-06T18:01:13.653038",{"slug":1883,"name":1883,"fn":3111,"description":3112,"org":3113,"tags":3114,"stars":24,"repoUrl":25,"updatedAt":3118},"write GraphQL queries and mutations","Guide for writing GraphQL operations (queries, mutations, fragments) following best practices. Use this skill when: (1) writing GraphQL queries or mutations, (2) organizing operations with fragments, (3) optimizing data fetching patterns, (4) setting up type generation or linting, (5) reviewing operations for efficiency.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3115,3116,3117],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":14,"slug":15,"type":16},"2026-04-06T18:01:25.530906",{"slug":1876,"name":1876,"fn":3120,"description":3121,"org":3122,"tags":3123,"stars":24,"repoUrl":25,"updatedAt":3128},"design GraphQL schemas","Guide for designing GraphQL schemas following industry best practices. Use this skill when: (1) designing a new GraphQL schema or API, (2) reviewing existing schema for improvements, (3) deciding on type structures or nullability, (4) implementing pagination or error patterns, (5) ensuring security in schema design.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3124,3125,3126,3127],{"name":2951,"slug":2952,"type":16},{"name":9,"slug":8,"type":16},{"name":18,"slug":19,"type":16},{"name":14,"slug":15,"type":16},"2026-04-06T18:01:19.140592",{"slug":1706,"name":1706,"fn":3130,"description":3131,"org":3132,"tags":3133,"stars":24,"repoUrl":25,"updatedAt":3139},"manage GraphQL schemas with Apollo Rover","Guide for using Apollo Rover CLI to manage GraphQL schemas and federation. Use this skill when: (1) publishing or fetching subgraph\u002Fgraph schemas, (2) composing supergraph schemas locally or via GraphOS, (3) running local supergraph development with rover dev, (4) validating schemas with check and lint commands, (5) configuring Rover authentication and environment, (6) exploring or searching a graph's schema for agent-driven discovery (rover schema describe \u002F rover schema search).\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[3134,3135,3138],{"name":9,"slug":8,"type":16},{"name":3136,"slug":3137,"type":16},"CLI","cli",{"name":14,"slug":15,"type":16},"2026-07-30T05:31:52.675547",15]