Repository navigation
Conversation
The control plane reference listed GET /oauth/authorize and described /oauth/token as the authorization code endpoint only. HandleOAuthAuthorize serves GET and POST (internal/controlplane/sts.go:1347-1352), and HandleOAuthToken dispatches grant_type token-exchange as well as authorization_code (internal/controlplane/sts.go:1539-1563). For a JWT subject_token the exchange mints a Delegated Session Biscuit (internal/controlplane/sts.go:1747). For a Biscuit subject_token it returns that Biscuit, attenuated when the request carries task parameters (internal/controlplane/sts.go:1719-1726, api/tar.go:635-637).
The control plane reference said every enrollment, refresh and STS request carries challenge_unix_ms and challenge_signature in the body. GET /revocations, GET /policies, GET /egress and POST /nodes/catalog read them from the X-Mesh-Challenge-Ts and X-Mesh-Challenge-Sig headers and answer 401 without them. The helper is admittedNodeWithChallenge (internal/controlplane/server.go:1875-1889, 2502-2506), called from internal/controlplane/server.go:1703 and 1989, internal/controlplane/sts.go:719 and internal/controlplane/catalog.go:121.
The admin table implied approve and reject answer protojson and listed no error codes. Both write 200 with a plain-text body (internal/controlplane/server.go:2941-2942, 3062-3063). A request already resolved answers 409 (internal/controlplane/server.go:2924, 2933, 3052). Approve answers 410 for a token revoked, expired or spent since the request was queued, and 403 for a banned token owner (internal/controlplane/server.go:2959-2973). The HTTP API and Admin intros said every request and response is a protojson or protobuf message. The intros now name the exceptions. /healthz and /readyz write a JSON status (internal/controlplane/server.go:783-813). Approve, reject and /user/revoke write plain text. POST and PUT /policies also take binary protobuf and answer in the encoding of the request (internal/controlplane/server.go:1732-1790).
The admin table showed /admin/revoke with an ad-hoc JSON body. The handler decodes api.TokenRevokeRequest, as protojson when the request is application/json and as binary protobuf otherwise, and answers api.TokenRevokeResponse in the same encoding (internal/controlplane/server.go:3167-3179, 3215-3221).
The user table said /user/bootstrap-tokens takes the same body as the admin route. A caller who is not an administrator is refused with 403 for a role other than mesh:role:node or for autonomous_recovery, and with 400 for ttl_hours over 168 or max_usages over 10 (internal/controlplane/server.go:3454-3455, 3480-3486, 3502-3508).
The user table said /user/revoke bans one of the caller's own nodes and named no parameter. The peer ID comes from the id query parameter (internal/controlplane/server.go:3583), an administrator may ban any node (internal/controlplane/server.go:3608-3609), and the handler answers 200 with a plain-text body (internal/controlplane/server.go:3623-3624).
The control plane reference did not say which routes send CORS headers. meshSurface sends Access-Control-Allow-Origin: * and answers OPTIONS with 204 (internal/controlplane/server.go:443-456). RegisterRoutes wraps the unauthenticated routes except /healthz, /readyz, /metrics and /oauth/authorize, and the mesh routes except /routers/lease and /nodes/catalog (internal/controlplane/server.go:389-413). Routes under /admin/ and /user/ get no CORS headers. POST and PUT /policies get them, because one wrapped handler serves every method of /policies (internal/controlplane/server.go:400).
The node API reference said Authorization carries the token only on
/mcp, /v1/*, /egress/* and /oauth/*. Every route reads it except the
proxy path, /mesh/{peer-id}/{type}/{name}. withAuth has the fallback on
for /metrics, /mesh/identity, /mesh/peer/ and /debug/
(internal/node/sidecar.go:68, 83-94). withCallerOrTokenAuth has it on
for /mesh/service/discover, /v1/*, /egress/, /mcp and CONNECT
(internal/node/sidecar.go:76, 108-123,
internal/node/egress_tunnel.go:308). authenticateSidecarCaller reads it
for /oauth/* (internal/node/sts.go:685). Only the proxy passes the
fallback off (internal/node/sidecar.go:99).
The node API reference said /readyz answers 200 while the process is up. handleReadyzFor answers 503 until the node holds an authenticated connection to a router (internal/node/sidecar.go:386-396, internal/node/node.go:892-900).
The node API reference said every route except /debug/* and /.well-known/* answers 503 until the node is connected to the mesh. Only the handlers behind withMeshConnection do: /mesh/service/discover, /mesh/peer/, the proxy path, /v1/* and /mcp (internal/node/sidecar.go:76, 88, 99, 108-110, 123). /metrics, /mesh/identity, /egress/, /oauth/*, the Envoy routes and CONNECT answer while the node is disconnected (internal/node/sidecar.go:57-68, 83, 117, internal/node/egress_tunnel.go:306-320).
The node API reference listed /oauth/revoke as needing the token. The handler revokes a Biscuit that verifies under a trusted control plane key without authenticating the caller (internal/node/sts.go:744-755). The comment on handleNodeOAuthRevoke said the handler caches the root Block 0 revocation ID. RevokeBiscuitToken caches the ID of the last block, so the parent token stays valid (internal/node/node.go:310).
The node API reference said / is an alias for /mcp. The MCP handler is mounted at / (internal/node/sidecar.go:123), but its inner mux registers only /mcp (internal/node/mcp.go:187), so a request to / answers 404.
The node API reference and the boundaries page (site/content/docs/concepts/boundaries.md) said /mesh/identity returns the credential, the key it verifies under, the peer ID, roles, labels and expiry, and that the peer evidence route returns the same. IdentityEvidenceResponse carries peer_id, biscuit, biscuit_expire_time, control_plane_url, trusted_control_plane_keys and check_time (internal/node/identity_evidence.go:249-256, api/agentmesh.proto:823-830) as protojson (internal/node/identity_evidence.go:159). Only PeerEvidenceResponse carries verifying_key, roles, labels, expire_time and revocation_ids (api/agentmesh.proto:832-841).
The node route table listed /debug/* as GET. connect-peer is registered as POST (internal/node/debug_handlers.go:74), as the Debug section already says.
The node API reference and a comment in cmd/chaos-agent/agent.py said the older SSE transport is refused with 400. The MCP server runs stateless (internal/node/mcp.go:159), and the stateless handler of the library go-sdk v1.8.0 answers every method but POST with 405 (~/go/pkg/mod/github.com/modelcontextprotocol/go-sdk@v1.8.0/mcp/streamable.go:381-384). cmd/chaos-agent/README.md said the agent connects via SSE. The agent opens a streamable_http_client (cmd/chaos-agent/agent.py:97).
The node API reference listed four fields for get_mesh_info. The tool returns meshInfo whole, whose first field is peer_id (internal/node/mcp_handlers.go:122, internal/node/debug_handlers.go:132-136).
The node API reference named only the v3 gRPC path, envoy.service.auth.v3.Authorization/Check. The gateway also mounts /envoy.service.auth.v2.Authorization/Check and rewrites it to the v3 path before dispatch (internal/envoy/server.go:51, 113, 120-128).
The router metrics table and the help text of agentmesh_router_streams_refused_total said a refused stream on /mesh/kad/1.0.0 or /meshsub/* is a member kept out of discovery. A member builds no DHT and is a floodsub leaf of the gossip (internal/node/node.go:709-712). A member reaches the directory on /mesh/directory/1.0.0 (api/directory_keys.go:31), and after a refusal it asks the next router it holds (internal/node/directory_client.go:210-224). Peer routers place records on that protocol too (internal/router/directory.go:425). Only peer routers speak /mesh/kad/1.0.0, and the control plane joins the gossip as a gossipsub peer (internal/controlplane/mesh.go:165).
The node route table linked #token-endpoint-oauthtoken. Hugo renders the heading as #token-endpoint-oauthtoken-and-revocation-oauthrevoke, and the site build reports the link as broken.
Contributor
There was a problem hiding this comment.
Code Review
This pull request updates documentation, code comments, and metric help text across the repository to align with the current implementation of the Agent Mesh APIs. Key updates include documenting the Streamable HTTP transport for MCP (replacing SSE), detailing OAuth 2.1 token exchange and revocation behaviors, specifying CORS and challenge headers, and clarifying response structures for identity evidence, admin, and user endpoints. No code changes were made to Go logic, and there are no review comments to address; therefore, I have no feedback to provide.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The control plane and node API references are what client authors code against. Nineteen statements there disagree with the handlers: methods, encodings, status codes, which routes accept which credentials, and what some routes return.
What changed
/oauth/authorizetakes POST, and/oauth/tokenalso serves RFC 8693./admin/revoketakesTokenRevokeRequestin either encoding./user/revokenames the node in?id=.Authorizationon every route but the proxy path./readyzand several other routes answer 503 until the node holds a router connection, and the page names the routes that answer while disconnected./oauth/revokeaccepts a verifying Biscuit without a token./is not an alias for/mcp, and a GET on/mcpanswers 405./mesh/identityreturns no roles or labels./debug/connect-peeris POST.get_mesh_infoalso returnspeer_id.Scope
/mesh/identityclaim and is fixed in the same commit.Verification
internal/controlplane,internal/nodeandinternal/router, and the MCP library's stateless handler. An independent review confirmed the new text, and its corrections are in.make lintpasses. The site builds with Hugo 0.147.5 and has no broken link.