Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
The decision framing (table, rule-of-thumb thresholds, failure-mode section) is genuinely useful and reads well. Two code samples use APIs that do not exist, which is blocking for a customer-facing reference doc whose stated purpose is correct, copy-pasteable examples.
-
Rhai header methods are fictitious. The router's Rhai header object uses an indexed accessor, not method calls.
headers.remove(...),headers.contains(...), andheaders.set(...)are not part of the documented Rhai surface (https://www.apollographql.com/docs/graphos/routing/customization/rhai/reference). Reads use the indexed accessor (request.subgraph.headers["x"]) orvalues()for multi-value; writes assign to the index. Removal is done by assigning empty/overwriting, not.remove(). As written, this script will not run. Thesubgraph_service(service, subgraph)signature andrequest.subgraph.headerspath are correct; only the method calls are wrong. -
The JS coprocessor sample imports a package and class that do not exist. There is no
@apollo/router-coprocessorpackage exposing anApolloRouterCoprocessorbuilder with.onSupergraphRequest().listen(). Apollo coprocessors are plain HTTP servers that respond to the router's stage payloads; this repo's owncoprocessor/uses Express +jose. Either rewrite the snippet against a real HTTP-server shape (ideally mirroringcoprocessor/src) or excerpt the existing coprocessor so the "canonical example layout" claim holds. -
Soften or verify the fail-open default claim. "The defaults are fail-open" is a security-relevant assertion; confirm it against the coprocessor configuration reference before stating it as the default, since getting this wrong in a doc about auth bypass is the exact failure the section warns about.
Fix the two API errors at minimum; align the coprocessor example with the in-repo implementation and confirm the failure-default wording.
| if request.subgraph.headers.contains("authorization") { | ||
| request.subgraph.headers.set("x-request-from-router", "true"); | ||
| } | ||
| }); | ||
| } |
There was a problem hiding this comment.
These header methods don't exist in the Rhai surface. The router exposes headers via an indexed accessor, not .remove()/.contains()/.set(). Per the Rhai reference, writes assign to the index and multi-value reads use values(); e.g. request.subgraph.headers["x-request-from-router"] = "true"; and read with request.subgraph.headers["authorization"]. There is no documented .remove(); overwrite/clear instead. As written this script fails to run.
There was a problem hiding this comment.
Verified at 33f64b1: the Rhai snippet now uses the indexed accessor for writes (request.subgraph.headers["x-request-from-router"] = "true") and contains() for the read, with no .remove()/.set() calls. The prose states there is no .remove() or .set() method and routes header removal to the YAML headers plugin. This thread can be resolved.
|
|
||
| new ApolloRouterCoprocessor() | ||
| .onSupergraphRequest(async (req) => { | ||
| const user = await directory.lookupBySub(req.context.entries.jwt_claims.sub); | ||
| req.context.entries.user_groups = user.groups; | ||
| return req; |
There was a problem hiding this comment.
@apollo/router-coprocessor and the ApolloRouterCoprocessor fluent builder don't exist. Coprocessors are plain HTTP servers handling the router's stage payloads; this repo's coprocessor/src uses Express + jose. Rewrite against that real shape or excerpt the in-repo coprocessor so the "canonical example layout" reference is accurate.
There was a problem hiding this comment.
Verified at 33f64b1: the coprocessor sample is now a plain Express HTTP server (import express, app.post("/"), reads payload.stage, returns res.json(payload)) with no @apollo/router-coprocessor import or ApolloRouterCoprocessor builder. The prose states there is no Apollo SDK and points to the in-repo coprocessor/ directory; I confirmed coprocessor/src/index.ts uses the same Express shape. This thread can be resolved.
|
|
||
| ## See also | ||
|
|
||
| - [Router Rhai docs](https://www.apollographql.com/docs/router/customizations/rhai) |
There was a problem hiding this comment.
"The defaults are fail-open" is security-relevant; confirm against the coprocessor configuration reference before asserting it as the default, then keep or correct the wording.
There was a problem hiding this comment.
Verified at 33f64b1: the fail-open claim is reversed. The table and Failure modes section now state coprocessors are fail-closed (unreachable/non-2xx/timeout/shape-mismatch returns an error to the client) and note there is no per-stage fail_open/fail_closed toggle, matching the coprocessor configuration reference. This thread can be resolved.
… (AS-319) Address docs-reviewer feedback on three blocking accuracy issues: 1. Rhai header methods. The Rhai surface has no .remove()/.set() — only indexed accessor (`headers["x"] = ...`), contains(), and values() for multi-value reads. Rewrite the snippet against the real API, and note that header removal lives in the YAML header-propagation plugin, not Rhai. 2. Coprocessor SDK. `@apollo/router-coprocessor` and the ApolloRouterCoprocessor fluent builder don't exist; coprocessors are plain HTTP servers. Rewrite against the actual shape used by this repo's coprocessor/src (Express + JSON payload echo). 3. Failure mode. Coprocessor failures are fail-closed by default (timeout / non-2xx / shape mismatch → error to client), with no per-stage fail-open toggle. The previous "defaults are fail-open" claim was wrong; reframe around the documented behaviour and what that implies for coprocessors on non-critical stages. Also repoint Rhai and coprocessor See-also links to the current /docs/graphos/routing/customization/ IA. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Re-reviewed at 33f64b1. All three blocking items from the prior review are resolved and verified against the file and the in-repo coprocessor.
- Rhai header surface: the snippet uses the indexed accessor for writes and contains() for reads, with no fictitious .remove()/.set() method calls. The prose correctly directs header removal to the YAML headers plugin.
- Coprocessor example: rewritten as a plain Express HTTP server matching coprocessor/src/index.ts (app.post("/"), reads payload.stage, returns res.json(payload)); the bogus @apollo/router-coprocessor package and ApolloRouterCoprocessor builder are gone.
- Failure default: the fail-open claim is reversed to fail-closed throughout, consistent with Router coprocessor behavior, and correctly notes there is no per-stage toggle.
The decision table, rule-of-thumb thresholds, and failure-mode section remain clear and accurate. Examples are correct and copy-pasteable. Approving.
Summary
Adds
docs/router-customizations.md. Decision-first comparison table covering latency, deployability, failure modes, and what each is good at. Includes worked examples in Rhai (header transformation) and a coprocessor (claim enrichment via directory I/O). Surfaces the fail-open vs fail-closed pitfall on coprocessor stages.Tracks AS-319.
Note
Placement: apollographql/docs archived; apollographql/platform-docs requires SAML.
Test plan
🤖 Generated with Claude Code