Skip to content

Enforce OAuth read-only for cloud commands#99

Merged
sdairs merged 19 commits intomainfrom
issue-98-oauth-read-only
Apr 9, 2026
Merged

Enforce OAuth read-only for cloud commands#99
sdairs merged 19 commits intomainfrom
issue-98-oauth-read-only

Conversation

@sdairs
Copy link
Copy Markdown
Collaborator

@sdairs sdairs commented Apr 9, 2026

Summary

  • OAuth device flow tokens are now treated as read-only. Write commands (create, update, delete, start, stop, scale, etc.) are blocked early in the CLI when using Bearer auth, with a clear error guiding users to API key authentication.
  • Every cloud command is explicitly classified as read or write using exhaustive match (no wildcards), so new commands must be classified at compile time.
  • 403 responses from the API when using OAuth now include a helpful hint about switching to API key auth (belt and suspenders).
  • cloud auth status now shows [read-only] / [read/write] labels.
  • Help text, CONTEXT FOR AGENTS sections, and README updated to document the read-only scope.

Closes #98

Changes

File What
src/cloud/client.rs is_bearer_auth() method + OAuth hint on 403 errors
src/cloud/cli.rs is_write_command() with exhaustive matching + updated help text
src/main.rs Pre-check gate in run_cloud() + [read-only]/[read/write] in auth status
src/cli.rs Updated top-level and Cloud CONTEXT FOR AGENTS
README.md Auth docs: OAuth is read-only, API keys required for writes

Test plan

  • cargo build — compiles
  • cargo test — all 251 tests pass
  • cargo clippy — clean
  • cargo run -- cloud auth status — verify [read-only] / [read/write] labels
  • cargo run -- cloud --help — verify updated agent context
  • cargo run -- cloud auth login --help — verify read-only note
  • Manual: OAuth login + attempt service create → clear error message
  • Manual: API key login + service create → works normally

Follow-ups

  • Update agent skills in ClickHouse/agent-skills repo
  • Rebase PR add signup command #78 (signup command) on top of this
  • Launch blog post and docs updates

🤖 Generated with Claude Code

…date docs

OAuth device flow tokens are now treated as read-only. Write commands
(create, update, delete, start, stop, scale, etc.) are blocked early
in the CLI when using Bearer auth, with a clear error guiding users
to API key authentication.

- Add is_bearer_auth() to CloudClient to expose auth mode
- Add is_write_command() to CloudCommands with exhaustive matching
  (no wildcards) so new commands must be classified at compile time
- Pre-check gate in run_cloud() blocks writes before API calls
- 403 responses with OAuth include a hint about API key auth
- auth status now shows [read-only] / [read/write] labels
- Updated help text, CONTEXT FOR AGENTS, and README

Closes #98

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs requested a review from iskakaushik as a code owner April 9, 2026 11:06
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 11:06 — with GitHub Actions Inactive
The command `cloud auth keys` doesn't exist. Replace with the actual
`cloud auth login --api-key KEY --api-secret SECRET` syntax, and note
the read-only vs read/write distinction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 11:32 — with GitHub Actions Inactive
sdairs and others added 2 commits April 9, 2026 12:36
Replace sample-based tests with exhaustive coverage of all 44 cloud
command variants. Tests parse real CLI args through clap, validating
both parsing and read/write classification.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add https://clickhouse.com/docs/cloud/manage/openapi?referrer=clickhousectl
to the pre-check gate error, 403 OAuth hint, no-credentials error, and README.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 11:40 — with GitHub Actions Inactive
sdairs and others added 5 commits April 9, 2026 12:40
Previously only hidden in release builds. This is an internal flag for
testing against staging/dev environments and should never be visible
to users or agents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…learing

`cloud auth logout` still clears everything by default. New flags:
  --oauth     clear only OAuth tokens, keep API keys
  --api-keys  clear only API keys, keep OAuth tokens

The flags are mutually exclusive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 11:48 — with GitHub Actions Inactive
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 11:56 — with GitHub Actions Inactive
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 12:06 — with GitHub Actions Inactive
sdairs and others added 2 commits April 9, 2026 13:08
The OAuth read-only note already covers this.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New order: CLI flags > file credentials > env vars > OAuth tokens.

API keys are project-scoped (read/write) and should take precedence.
OAuth is user-scoped (read-only) and serves as a fallback when no
API keys are configured.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 12:14 — with GitHub Actions Inactive
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 12:49 — with GitHub Actions Inactive
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 13:07 — with GitHub Actions Inactive
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 13:16 — with GitHub Actions Inactive
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 15:35 — with GitHub Actions Inactive
Restore cfg_attr(debug_assertions) so --url is visible in debug builds
but hidden in release builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sdairs sdairs temporarily deployed to cloud-integration April 9, 2026 15:44 — with GitHub Actions Inactive
@sdairs sdairs merged commit 5802887 into main Apr 9, 2026
10 checks passed
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.

OAuth device flow should be read-only; destructive commands require API key auth

3 participants