Skip to content

feat(api-keys): roboflow api-key CLI#495

Merged
yeldarby merged 11 commits into
mainfrom
api-key-management
Jul 2, 2026
Merged

feat(api-keys): roboflow api-key CLI#495
yeldarby merged 11 commits into
mainfrom
api-key-management

Conversation

@yeldarby

Copy link
Copy Markdown
Contributor

Adds a roboflow api-key CLI command group (list / get / create / update / revoke / protect / disable / publishable) wrapping the new REST endpoints.

  • Secret shown once on create; non-secret keyId handles; --scope / --metadata on create + update; protected-key 409 and plan-feature 403 hints; consistent exit codes and --json envelopes.
  • Tests in tests/cli/test_api_key.py; version bump.

🤖 Generated with Claude Code

yeldarby and others added 2 commits June 19, 2026 23:06
Checkpoint of the API key management feature work (round 1 + refinement pass).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… hint

Round-2 refinement fixes (independent re-review).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread roboflow/cli/handlers/api_key.py Fixed
yeldarby and others added 4 commits June 20, 2026 10:02
Emit the create result (incl. the one-time secret) via the shared output() helper like every other handler, instead of a raw print(). Resolves a CodeQL clear-text-logging alert and matches the repo's documented output idiom; stdout is unchanged in both --json and human modes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sets

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… + presets

External review (P2): omitting scopes inherits the caller's scopes (not unconditional full access); note role:<name> presets and [] for no abilities.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
External review (skills PR): the command-groups reference omitted api-key, so agents couldn't discover it. The group ships in this PR.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
digaobarbosa
digaobarbosa previously approved these changes Jun 22, 2026

@digaobarbosa digaobarbosa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after API merge

Explain the create privilege (unscoped or api-key:create; OAuth also needs create_api_key) and the all-folder requirement for workspace-wide keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@davidnichols-ops

Copy link
Copy Markdown

Was looking at this PR and noticed a few things — posting in case any of it's useful. I'm not affiliated with Roboflow, just an outside contributor who happened to dig in.

CI failure is repo-wide, not from this PR

All 8 build jobs fail at the mypy roboflow step with the same error:

numpy/__init__.pyi:737: error: Type statement is only supported in Python 3.12 and greater  [syntax]
Found 1 error in 1 file (errors prevented further checking)
make: *** [Makefile:13: check_code_quality] Error 2

The failure is in numpy's type stub file, not in any file this PR touches. ruff check and ruff format --check pass cleanly on this PR; test-slim is green; the PR's own test suite (tests/cli/test_api_key.py, 42 tests) passes locally.

This looks like a numpy 2.5.0 × mypy interaction — numpy 2.5.0 ships stubs using the Python 3.12+ type statement syntax, and mypy roboflow fails parsing them before reaching the project's own code.

To confirm it's repo-wide: the same failure hits an unrelated PR the same day — the pre-commit-ci bot's chore(pre_commit): ⬆ pre_commit autoupdate (run 28391383808), which only bumps pre-commit hook versions and touches none of this PR's files. main was last pushed June 9 (before numpy 2.5.0 was cached), which is why it's still green.

Likely fixes (for maintainers, not this PR): pin numpy<2.5, bump mypy, or exclude numpy stubs from the mypy step.

Likely bug: custom_metadata sent as snake_case

In roboflow/adapters/rfapi.py:1521, the create body uses body["custom_metadata"] (snake_case), but every other multi-word body key in the file is camelCase:

Line Key Convention
124 continueIfNoRefund camelCase
290 annotationGroup camelCase
413 removeMetadata camelCase
415 addTags camelCase
684 batchName camelCase
1519 folderIds camelCase
1521 custom_metadata snake_case ← outlier

The backend almost certainly expects customMetadata to match folderIds in the same request. If so, metadata is silently dropped on every api-key create call that passes --metadata.

The same flows through _update_key at roboflow/cli/handlers/api_key.py:349 (fields["custom_metadata"]), and the update_api_key docstring at rfapi.py:1534 references custom_metadata.

No test catches this because every existing test mocks at the Python function level (mock_create.assert_called_once_with(...)) and never inspects what requests.post actually sends. The TestStatusCodePropagation class already mocks requests.* but only checks status_code, not the body.

Suggested fix: body["custom_metadata"]body["customMetadata"] at rfapi.py:1521, and fields["custom_metadata"]fields["customMetadata"] at api_key.py:349. Plus a test that mocks requests.post and asserts call_args.kwargs["json"] contains customMetadata (camelCase).

Caveat: I'm inferring customMetadata from the convention of every sibling key. The backend owner should confirm the exact field name before merging.

Minor: error hint accuracy

A few of the error hints are broader than they should be. Not blockers, but worth a look:

_create_key (api_key.py:296–316): if status in (403, 404) gives the same hint for both. A 404 means "workspace or endpoint not found", not "you lack the api-key:create scope" — the scope hint is misleading for 404. The else branch gives a plan-feature hint for every other status including 401 (auth), which is confusing. Suggested: split 403 and 404, and only apply the plan-feature hint for 403.

_update_key (api_key.py:351–359): doesn't special-case 403 (plan feature) or 409 (protected key) the way _disable_key does (api_key.py:401–422). A user hitting api-key update <id> --scope image:read without the plan feature gets a generic error with no "Advanced API Keys" hint.

_protect_key (api_key.py:375–382): passes the "The API cannot unprotect a key..." hint for every error including 500s and 401s. That hint only makes sense for 403. Suggested: scope it to 403 only.

Minor: missing CHANGELOG + CLI-COMMANDS.md examples

  • roboflow/__init__.py:24 bumps the version to 1.3.11, but CHANGELOG.md has no ## 1.3.11 section (every prior release has one).
  • CLI-COMMANDS.md got a table row for api-key (line 360) but no usage examples subsection — every other command group has one (e.g. ### Inspect model evaluations at line 245).

What's already good

  • All 42 tests in tests/cli/test_api_key.py pass locally.
  • ruff check and ruff format --check are clean on the PR's files.
  • Exit-code contract (0/1/2/3) is correctly implemented and tested.
  • --json output and destructive-confirmation gating are correct.
  • Handler registration, alphabetical ordering, and ctx_to_args bridge all follow the repo's conventions.

Hope this is helpful — happy to elaborate on any of it.

yeldarby and others added 2 commits June 30, 2026 23:38
Adds --no-scopes ([]), --full-access (explicit null/unscoped), and --clear-metadata ({}) to 'roboflow api-key create/update', mutually exclusive with --scope/--metadata. Adds a backward-compatible FULL_ACCESS sentinel to rfapi.py so create_api_key/update_api_key can emit an explicit null scopes value (previously None only meant omit). 18 new CLI tests; full CLI suite green, ruff + mypy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
numpy 2.5.0 ships type stubs that use the Python 3.12+ `type` statement
syntax, which mypy — pinned to python_version 3.10 in pyproject.toml —
rejects while parsing numpy/__init__.pyi. That fails `make check_code_quality`
on every build-matrix job, repo-wide and unrelated to this PR's code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@socket-security

socket-security Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​numpy@​2.5.0 ⏵ 2.4.675 +110010010070
Updatedpypi/​matplotlib@​3.11.0 ⏵ 2.2.580 +610010010090 +10

View full report

@socket-security

socket-security Bot commented Jul 1, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: pypi numpy is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: requirements.txtpypi/numpy@2.4.6

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore pypi/numpy@2.4.6. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

yeldarby and others added 2 commits July 1, 2026 13:41
Serialize the Pythonic `custom_metadata` kwarg to the canonical camelCase `customMetadata` wire field (consistent with `folderIds`) on create and update. The public Python parameter name is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@digaobarbosa digaobarbosa self-requested a review July 1, 2026 22:21
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.

4 participants