Skip to content

Prepare v0.9.1: fix review gaps and stamp the changelog - #152

Merged
leet-c1 merged 9 commits into
mainfrom
chore/release-0.9.1-prep
Oct 9, 2026
Merged

leet-c1 merged 9 commits into
mainfrom
chore/release-0.9.1-prep

Conversation

@leet-c1

@leet-c1 leet-c1 commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Housekeeping before cutting v0.9.1. It fixes the gaps a pre-release review found across everything merged since v0.9.0 (#147–#151), and stamps the changelog.

Fixes

  • docs endpoint output is now deterministic. The $ref resolver shared one "seen" set across sibling nodes and walked maps in Go's random order, so whichever sibling came first got the expanded schema. 12 runs of docs endpoint /api/v1/users gave 7 different outputs; it now gives 1. Keys are visited in sorted order, and nothing is dropped: a later sibling's bare $ref points at an expansion earlier in the same output.
  • No home directory means no OpenAPI cache. When the home dir is unknown, the cache is skipped. Before, the spec was written into ./.c1i/cache/ in the working directory.
  • A bad download no longer poisons the cache. A 200 response is cached only if it parses as an OpenAPI document with paths. The write is atomic (temp file, then rename), and the leftover-file prune runs only after a successful rename. On an unparseable body or a failed read, c1i falls back to the existing cache.
  • A stale cache is no longer served silently. When a fetch fails and an expired copy is served, c1i prints one line on stderr naming its age, for example Warning: using cached OpenAPI spec from 3d ago (…). stdout is unchanged. A fresh cache hit stays silent.

Docs and help

  • Bash completion: now installs to ~/.local/share/bash-completion/completions/c1i. The old path needed root.
  • Service principals: delete and credentials revoke are soft. get and credentials get still return the record at exit 0, with no field marking it. Verified live on a lab tenant: the principal's user.status stays ENABLED, only the lists omit the record, and users get <sp-id> shows "status": "DELETED". This is in the README, the help text, and cmd/agents.md.
  • docs endpoints --filter: the help now says it also matches operation descriptions.
  • agents.md: notes the stale-cache warning, and one paragraph is rewrapped.

Tests

  • Delete-safety gaps closed:
    • the cache prune leaves an empty subdirectory alone;
    • the token sweep leaves token-shaped decoys in the config root and in the c1i dir alone;
    • the prune's relative-dir guard has a direct test again.
  • Windows-safe: the cache tests now set USERPROFILE as well as HOME.
  • Mutation-checked: each new test was confirmed to fail on a mutant that removes its fix. Independent review re-ran 14 mutants: 12 are killed, and the 2 that survive are harmless cleanup paths.

CHANGELOG

  • Stamped ## [0.9.1] - 2026-10-09, with an empty [Unreleased] above and the link refs updated.
  • Security comes first: v0.9.0 binaries were built with Go 1.27.1, which carries 9 vulnerabilities in code c1i calls.
  • Upgrading from 0.9.0 lists the behavior changes: the renamed cache file, the prune of foreign files in ~/.c1i/cache/, and the token-file sweep.

Verification

  • Gates (Go 1.27.2):
    • build, plus vet for linux and windows;
    • go test -count=1 -shuffle=on with 3 seeds;
    • golangci-lint (0 issues) and gosec with the CI flags;
    • govulncheck on linux, darwin and windows: 0 called vulnerabilities;
    • go mod tidy and gitleaks;
    • cross-compiles for darwin/arm64, windows/amd64 and linux/arm64;
    • no outdated direct dependencies.
  • Live checks:
    • 10 runs of docs endpoint give one hash;
    • with HOME unset, nothing is written to the working directory;
    • an offline fallback prints the warning, with stdout clean.
  • Reviews: independent code and docs/CHANGELOG reviews, re-checked after fixes.

After merge

  1. Tag v0.9.1.
  2. Update the public docs pages in a separate PR: the new spec source and cache, an uninstall section, the token sweep, and the soft-delete note.

🤖 Generated with Claude Code

leet-c1 and others added 9 commits October 9, 2026 02:20
resolveRefs shares one seen set across sibling keys, so only the first
sibling to reach a shared $ref gets it expanded; later ones keep the bare
$ref. Ranging over the map picked that sibling at random, so the same
endpoint printed different schemas from run to run. Visit keys in sorted
order so the same sibling wins every time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The OpenAPI cache tests set only HOME, but os.UserHomeDir reads
  USERPROFILE on Windows, so they could write to a developer's real cache.
  Set both.
- The prune test's only subdirectory was non-empty, so dropping the
  IsDir check went unnoticed. Add an empty one and require it to survive.
- The token sweep test now plants expired token-shaped files in the config
  root and the c1i dir, with the root at 0700 so the trust check doesn't
  mask a sweep that reaches above tokens/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With HOME unset, or set to a relative path, the docs openapi, endpoints
and endpoint commands read and wrote the spec cache under ./.c1i/cache in
the working directory. Without an absolute home dir they now fetch the
spec and use it directly, touching no cache at all.

The test that held the prune off a working-dir cache becomes a test that
the working dir is left untouched: nothing read, written or pruned.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A 200 whose body isn't a spec, such as a captive portal's sign-in page,
was written to the cache before anything parsed it, so every docs
openapi/endpoints/endpoint call failed for the next 24 hours. The body is
now cached only when it parses as YAML with a paths key; otherwise the
existing cache is used, however old, or the command fails with an error
naming the URL. A read that fails mid-body falls back the same way.

The cache is written to a temp file in the same directory and renamed
into place, so a reader never sees a partial file. The prune still runs
after the rename, so it never removes this process's temp file, and it
sweeps one a crash left behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Verified live: after delete, service-principals get still returns the
principal with exit 0. No field marks it deleted; its embedded
user.status stays ENABLED and only updatedAt changes. users get on the
same id shows status DELETED and deletedAt. After revoke, credentials get
returns the credential unchanged. Both lists omit them. Say so in the
README and in the help for get and credentials get.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The bash completion example wrote to /etc/bash_completion.d, which
  needs root. Install to the per-user bash-completion directory instead.
- docs endpoints --filter also matches an operation's description; its
  help now says so.
- Rewrap an over-long line in agents.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stamp the unreleased entries as 0.9.1. Move the Go 1.27.2 entry under
Security and say plainly that v0.9.0 users should upgrade, move the
OpenAPI source change under Changed, add an Upgrading from 0.9.0 section
for the cache path and the two sweeps, and add entries for this release's
fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the fetch fails or returns something that isn't a spec, the docs
commands fall back to the cached spec however old it is, which is the
point offline, but did so silently. Print one line on stderr naming the
cache's age and the failure; stdout is unchanged so pipes keep working.
A fresh cache hit stays silent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Restores a direct test for pruneCacheDir's relative-dir guard, which the
replaced test no longer reached. Capitalizes the warning like the rest of
the CLI and clamps a future mtime to 0m. agents.md now notes the stale-cache
warning and the soft service principal delete and revoke.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@leet-c1
leet-c1 merged commit a793069 into main Oct 9, 2026
2 checks passed
@leet-c1
leet-c1 deleted the chore/release-0.9.1-prep branch October 9, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant