Repository navigation
Harden the spec fetch, token sweep and config paths - #153
Merged
Merged
Conversation
docs openapi, docs endpoints and docs endpoint used http.DefaultClient, so --debug and --max-retries were inert, a redirect to any host was followed, and the body was read without a size cap. The fetch now uses transport.New with both flags and a 32 MiB cap; cache, stale fallback and parse-before-cache are unchanged. Failures classify like upgrade's dist fetch: 4/5/6 for a 404/429/5xx, 8 otherwise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A cache file inside cacheMaxAge that failed to read (a permissions error, or a directory at the cache path) was returned as the command's error without trying the network. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pruneTokenDir read an expired <key>.json and then removed the path. A concurrent store renaming a fresh token over it in between lost the fresh token. Remove only when a second Lstat is os.SameFile with the first; on Windows the first stat's file id is pinned eagerly, since Lstat loads it lazily. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A relative HOME (Linux/macOS) or %AppData% makes os.UserConfigDir relative, so the credential file fallback and the token file cache wrote under the working directory. keychain.ConfigDir now refuses a non-absolute result: Store/Load fail with an error naming the path, and the token cache treats it as unavailable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Name the removal step per install method (Homebrew, go install, a downloaded binary, the container image), and note that the Linux config directory follows XDG_CONFIG_HOME. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Pulls golang.org/x/sys to v0.49.0. The outdated-direct-deps query listed x/term; govulncheck reports nothing called. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
upgrade ran `go env` to detect a go install, and any go command writes telemetry counters under the user's config dir; GOTELEMETRY=off doesn't stop it. readGoEnv now follows the go command's order itself: the environment, then $GOENV or <UserConfigDir>/go/env (none with GOENV=off), then GOPATH's <home>/go default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With --max-retries defaulting to 4, an offline run with a stale cache took ~5s, and a blackholed network minutes, before the fallback. When a cache file exists the fetch now makes one attempt unless --max-retries or C1I_MAX_RETRIES is set; with no cache the configured retries apply. The docs also now say a redirect loop exits 6, not 8. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A CDN 403 must exit 8 (not 3) and a 200 that isn't a spec must exit 8 (not 1); both survived mutants replacing distError with a bare error. APIError also drops the trailing ": " when there is no body. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With HOME="." viper's config path and SaveToConfigFile both resolved to the working directory, so a planted .c1i.yaml could redirect `url` (and env-var credentials with it). config.HomeDir refuses a relative home: the config file is then neither read nor written, and login's save reports the error as its existing warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add "Upgrading from 0.9.1" for the docs exit codes, default retries and relative-HOME behavior; stop claiming go-install detection is unchanged now that Go's env file is read without Go installed; tell agents that a relative HOME with no keyring makes the auth commands fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eds an absolute config dir Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Hardening items deferred from the v0.9.1 pre-release review, bundled into one PR.
Changes
The OpenAPI spec fetch goes through the shared transport.
docs openapi,docs endpointsanddocs endpointnow get:--debugtracing and--max-retries;4for a 404,5for a 429,6for a 5xx or a redirect loop,8for anything else. These apply when no cache is available.When a cached spec exists, the fetch makes one attempt, because the stale cache is the fallback. An explicit
--max-retriesorC1I_MAX_RETRIESoverrides that. Offline with a stale cache, a run takes 139 ms instead of 5.4 s.This retires a documented exception in CLAUDE.md.
docs searchanddocs pagestill bypass the transport.A fresh cache that can't be read triggers a re-fetch instead of an error.
A token-sweep race is fixed. The sweep checks the file again just before deleting it, and removes it only if it's still the same file. A fresh token that a concurrent c1i process renames into place is no longer deleted. On Windows, the file id is pinned first, because
Lstatloads it lazily.A relative home or config dir is refused. With a relative
HOMEor%AppData%, c1i no longer writes credentials, tokens or~/.c1i.yamlunder the working directory, and it no longer reads~/.c1i.yamlfrom there. Before, a.c1i.yamlplanted in a repo could redirecturl. IfC1I_CLIENT_IDandC1I_CLIENT_SECRETwere set, those credentials would be sent to that host.upgradeno longer runsgo env. It readsGOBINandGOPATHfrom the environment and the Go env file, in Go's own precedence order. Runninggo envmade the Go toolchain onPATHwrite telemetry under the user's config dir.Uninstall docs now say where the binary lives for each install method, and that Linux follows
XDG_CONFIG_HOME.golang.org/x/termis bumped to v0.47.0, which bringsx/sysv0.49.0.The CHANGELOG
[Unreleased]section has an Upgrading from 0.9.1 note for scripts. It covers the new exit codes, the default retries when no cache exists, and the relative-home refusal.Verification
go test -count=1 -shuffle=onwith 3 seeds;go mod tidyand gitleaks;docs endpointsreturns 820 rows, anddocs endpointgives a deterministic hash;--debugtraces the fetch;./.c1i.yamlis ignored whenHOMEis relative;upgrade --checkwrites nogo/telemetryand still detects aGOBINinstall.Not included
cmdkeyalternative for removing keyring entries is left out of the uninstall docs. It couldn't be verified without a Windows host.max_retrieskey in~/.c1i.yamldoesn't override the one-attempt rule. That matches the README, which documents only the flag and the env var as sources.🤖 Generated with Claude Code