Update spec to v2.1.234; read methods and headers from the binary - #9
Update spec to v2.1.234; read methods and headers from the binary#9lroolle wants to merge 2 commits into
Conversation
Documents @anthropic-ai/claude-code@2.1.234 and corrects the extraction method
this repo has used since releases went binary-only.
The correction. Every previous revision carried this caveat:
Header sets, request bodies and timeouts are NOT recoverable from a Bun
binary -- those are read from v2.1.76, the last release with a readable
bundle, and carried forward explicitly labelled.
That was wrong, and has been since v2.1.117. The binary embeds the entire
minified JavaScript bundle as printable text. It reads as one enormous line, so
`rg -A/-B` context returns nothing useful and "not recoverable" looked like a
fair conclusion. Cut a fixed byte window instead and the call site is complete:
fs.get("/v1/ultrareview/quota", {auth: "teleport-org", timeout: 3000})
Methods, header sets, auth modes, timeouts and beta flags for v2.1.234 are now
read from v2.1.234.
Auth modes -- the most useful thing this recovered. axios call sites name their
auth mode and the mode decides the whole header set:
teleport-org Authorization + Content-Type + anthropic-version +
anthropic-client-platform + x-organization-uuid, and
substitutes the literal ":orgUUID" in the path -- which is
why paths in the constant pool contain it verbatim
session-jwt Authorization: Bearer <session access token>, nothing else
claude-ai-oauth Authorization + anthropic-beta: oauth-2025-04-20
none no auth headers
async / unset resolved OAuth headers, or x-api-key under API-key auth
Two pre-flight refusals apply to every axios call: essential-traffic-only mode,
and a non-first-party provider (data-residency).
New scripts, none hardcoding a minified identifier:
extract-routes.py method + path + beta + auth + timeout per call site.
Anchors the SDK shape on the literal `_client.`, detects
axios instances by frequency, resolves hoisted path
constants. 242 routes (129 SDK, 114 axios).
extract-calls.py printable byte window per endpoint anchor, replacing the
`rg -B 10 -A 20 cli.js` recipe that a one-line bundle
broke.
binary-literals.sh binary -> one-literal-per-line text; the input
validate-spec.sh needs for a compiled release.
validate-spec.sh: trims captures at URL-invalid characters (a binary capture
runs straight into adjacent data), widens the path scope to the families the
specs actually cover, normalises {server_id}-style placeholders, and takes
--routes so template-built paths stop reading as phantoms. Adds a `# PATH-ONLY`
declaration for a path literal whose call site builds it through a helper the
route extractor does not follow: the path is verified, the method is not, and
the spec says so instead of guessing. 47 such paths.
Both gates pass: 0 undocumented, 0 phantom for claude-code-api-complete.http
and (--subset) claude-oauth-api.http.
Surface changes: 101 path literals (+33), 53 beta flags (+9), 161 routes newly
written up. New families -- self-hosted runner pools, MCP tunnels, dreams,
deployments, Design consent/grants, ultrareview quota, a much larger frame
(Artifact) surface, local/org memory, plugin and skill search. Removed and
commented out as history: team_usage, team_memory, user_settings,
claude_cli/client_data, /v1/code/egress/gateway, /v1/code/upstreamproxy, and the
bare /v1/code/ root.
The embedded gateway protocol document grew 9,598 -> 13,246 bytes; recovered
whole to extractions/v2.1.234/GATEWAY-PROTOCOL.md. New sections: the overage
429 header contract, TLS leaf-certificate pinning, client guarantees, and
proxying to Bedrock/Vertex/Foundry.
Section 43 records a cross-check of the binary-derived header sets against a
local capture of one live v2.1.234 session. This does not infer endpoints from
runtime logs -- it checks facts already read from the binary. No identifiers,
tokens, request-ids or organization UUIDs from that capture appear anywhere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Section 42 is ~1,700 lines of request blocks derived mechanically from raw/routes.tsv. Those lines were generated, but the generator lived in /tmp -- so the largest single artifact in the change had no provenance, which is exactly the thing this repo exists to avoid. scripts/gen-spec-section.py now ships. It rewrites the section in place from the route table and is idempotent: run it twice, get the same bytes (verified). The split is explicit -- request blocks are generated, family grouping and prose are authored and live in the FAMILIES table inside the script, so editing prose in the .http file would be lost on the next run. This is also what makes the diff reviewable: the generated block is skimmed and re-derived, and review attention goes to the 370 lines of extraction scripts and the prose. Both gates still report 0 undocumented, 0 phantom. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Review note: provenance for the generated sectionPushed
How to review this PR
Reproduce end to end: scripts/binary-literals.sh <binary> /tmp/literals.txt
scripts/extract-routes.py <binary> --all extractions/v2.1.234/raw/routes.tsv
scripts/gen-spec-section.py 2.1.234 /tmp/literals.txt
scripts/validate-spec.sh --routes extractions/v2.1.234/raw/routes.tsv \
/tmp/literals.txt specs/claude-code-api-complete.httpKnown follow-up, deliberately not in this PR
|
Documents
@anthropic-ai/claude-code@2.1.234and corrects the extraction method this repo has used since releases went binary-only.The correction
Every previous revision of this repo carried the same caveat:
That was wrong, and it has been wrong since v2.1.117. The binary embeds the entire minified JavaScript bundle as printable text. It reads as one enormous line, so
rg -A/-Bcontext returns nothing useful and "not recoverable" looked like a fair conclusion. Cut a fixed byte window instead and the call site is right there, complete:Methods, header sets, auth modes, timeouts and beta flags for v2.1.234 are now read from v2.1.234, not carried forward from a two-year-old release. The same method works retroactively on older binaries.
Auth modes — the most useful thing recovered
axios call sites name their auth mode, and the mode decides the entire header set:
auth:teleport-orgAuthorization,Content-Type,anthropic-version,anthropic-client-platform,x-organization-uuid— and substitutes the literal:orgUUIDin the pathsession-jwtAuthorization: Bearer <session access token>onlyclaude-ai-oauthAuthorization,anthropic-beta: oauth-2025-04-20noneasync/ unsetx-api-keyunder API-key authThat last row also solves a long-standing oddity: paths in the constant pool contain
:orgUUIDverbatim because the auth layer, not the call site, substitutes it.Two pre-flight refusals apply to every axios call before a request is made: essential-traffic-only mode, and a non-first-party provider (
data-residency).New scripts
None of them hardcodes a minified identifier.
extract-routes.py_client., detects axios instances by frequency, resolves hoisted path constants. 242 routes (129 SDK, 114 axios), 120 with a beta flag.extract-calls.pyrg -B 10 -A 20 cli.jsrecipe that a one-line bundle broke.binary-literals.shvalidate-spec.shneeds for a compiled release.validate-spec.sh fixes
/api/hello,{headers:{)./v1/code,/v1/vaults,/v1/agents,/worker/…, …), which were silently reported as phantoms.{server_id}-style placeholders alongside${…}.--routesto union in the call-site table, so a path assembled from a template (/v1/environments/${id}/work/${w}/ack— never a whole literal) stops reading as a phantom.# PATH-ONLYdeclaration for a path literal whose call site builds it through a helper the route extractor doesn't follow. The path is verified, the method is not, and the spec says so instead of guessing. 47 such paths — so "0 undocumented" means every path literal is accounted for, not that every method is known.Both gates pass: 0 undocumented, 0 phantom for
claude-code-api-complete.httpand (in--subsetmode)claude-oauth-api.http.Surface changes
101 path literals (+33 vs v2.1.197), 53 beta flags (+9), 161 routes newly written up.
New families: self-hosted runner pools, MCP tunnels, dreams, deployments, Design consent/grants, ultrareview quota, a much larger frame (Artifact) surface, local/org memory, and plugin/skill search.
Removed — verified absent, commented out as history rather than deleted:
/api/claude_code/discovery/team_usage,/api/claude_code/team_memory,/api/claude_code/user_settings,/api/oauth/claude_cli/client_data,/v1/code/egress/gateway,/v1/code/upstreamproxy, and the bare/v1/code/root.Gateway protocol document
Grew 9,598 → 13,246 bytes; recovered whole to
extractions/v2.1.234/GATEWAY-PROTOCOL.md. New sections: the overage 429 header contract (including the trap where sendingrepresentative-claimmakes the client drop your message), TLS leaf-certificate pinning, client guarantees, and proxying to Bedrock/Vertex/Foundry.specs/claude-code-gateway.httpvalidates as "phantom" by design — it specifies the server side, and the CLI resolves those paths from the gateway's own discovery document. A note in the spec now says so.Cross-check against live traffic
WORKFLOW.md's rule stands: endpoints are never inferred from runtime logs. Section 43 goes the other way — it checks header sets already read from the binary against a local capture of one live v2.1.234 session. The capture confirms the auth-mode table exactly (/v1/code/triggersand/v1/ultrareview/quotawent out with the fullteleport-orgset;/mcp-registry/v0/serverswith noauthorizationat all).No identifiers, tokens, request-ids or organization UUIDs from that capture appear anywhere in this repository.
🤖 Generated with Claude Code