Skip to content

feat: support overriding authentication per request#115

Open
tada5hi wants to merge 2 commits into
mainfrom
feat/per-request-auth-override
Open

feat: support overriding authentication per request#115
tada5hi wants to merge 2 commits into
mainfrom
feat/per-request-auth-override

Conversation

@tada5hi

@tada5hi tada5hi commented Jun 23, 2026

Copy link
Copy Markdown

Summary

Adds an optional keyword-only auth parameter to every public client method (AuthClient, CoreClient, StorageClient) so the Authorization header can be overridden for a single request, while all other requests keep the client's bound authentication.

auth accepts:

  • an httpx.Auth instance (e.g. another PasswordAuth / ClientAuth),
  • a (username, password) tuple for HTTP basic auth, or
  • a string sent verbatim as the Authorization header (e.g. "Bearer <token>").

Following httpx conventions:

  • omit auth (default) → use the client's bound authentication,
  • pass an override → replace it for that request,
  • pass auth=None → send the request without any authentication.
core_client.get_nodes(auth="Bearer <token>")
core_client.create_node(name="my-node", realm_id=master_realm, auth=other_auth)
core_client.get_nodes(auth=None)  # no Authorization header

Implementation notes

  • New public types in flame_hub.types: RequestAuth (override forms) and RequestAuthArg (parameter type incl. the USE_CLIENT_DEFAULT / None sentinels).
  • A small internal _StaticAuthorization httpx auth flow wraps a raw header string; resolve_request_auth() maps the argument to an httpx-native value (string → wrapped, everything else passed through).
  • auth is threaded through the BaseClient request helpers and every public method. It is not part of GetKwargs / FindAllKwargs (it's a transport concern, not a query option).

Compatibility

Non-breaking — purely additive. All auth parameters default to USE_CLIENT_DEFAULT, preserving existing behavior.

Testing

  • Added unit tests (httpx.MockTransport, no containers) covering resolve_request_auth and the default / string-override / httpx.Auth-override / disable paths across read, find, create and delete — including the public client surface.
  • ruff format + ruff check clean; 88 passed (non-integration suite).

Summary by CodeRabbit

  • New Features

    • All API client methods now accept an optional per-request auth parameter to override the client's default authentication for individual requests.
  • Documentation

    • Updated README with a new "Overriding authentication per request" section documenting the per-request auth parameter, accepted formats, and usage examples.

Add an optional keyword-only `auth` parameter to every public client
method (AuthClient, CoreClient, StorageClient) to override authentication
for a single request, leaving the client's bound authentication in place
for all others.

`auth` accepts an httpx.Auth instance, a (username, password) tuple, or a
string sent verbatim as the Authorization header. Following httpx
conventions, omitting it keeps the client's bound auth and `auth=None`
disables authentication for that request.
Copilot AI review requested due to automatic review settings June 23, 2026 08:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@tada5hi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 54 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b9b8d14d-dba9-4764-9425-4f159209ac12

📥 Commits

Reviewing files that changed from the base of the PR and between c2f252b and 2a4bb68.

📒 Files selected for processing (3)
  • flame_hub/_core_client.py
  • flame_hub/_storage_client.py
  • tests/test_base_client.py
📝 Walkthrough

Walkthrough

The PR introduces per-request authentication overrides across the entire hub-python-client library. A RequestAuth/RequestAuthArg type alias, _StaticAuthorization httpx.Auth wrapper, and resolve_request_auth() resolver are added to BaseClient. All six BaseClient helper methods and every public endpoint method on AuthClient, CoreClient, and StorageClient gain a keyword-only auth parameter. The new types are re-exported from flame_hub/types.py, tests cover the resolver and integration paths, and README documents the feature.

Changes

Per-request authentication override

Layer / File(s) Summary
Auth types, resolver, and BaseClient helper wiring
flame_hub/_base_client.py
Adds RequestAuth, RequestAuthArg, _StaticAuthorization, and resolve_request_auth(). Updates all six BaseClient internal HTTP helpers (_get_all_resources, _find_all_resources, _create_resource, _get_single_resource, _update_resource, _delete_resource) to accept and forward auth via resolve_request_auth(auth).
Public type exports and README docs
flame_hub/types.py, README.md
Re-exports RequestAuth and RequestAuthArg from flame_hub/types.py. Adds a README section describing accepted auth forms, auth=None semantics, and Python usage examples.
AuthClient endpoint auth parameter wiring
flame_hub/_auth_client.py
Imports RequestAuthArg/USE_CLIENT_DEFAULT and adds keyword-only auth=USE_CLIENT_DEFAULT to every public method across realms, robots, permissions, roles, role-permissions, users, user-permissions, user-roles, robot-permissions, robot-roles, and clients.
CoreClient endpoint auth parameter wiring
flame_hub/_core_client.py
Imports auth plumbing and adds keyword-only auth to every public method for nodes, master images, projects, project-nodes, analyses, analysis-nodes, logs, buckets, bucket-files, registries, and registry-projects; direct httpx calls use resolve_request_auth(auth).
StorageClient endpoint auth parameter wiring
flame_hub/_storage_client.py
Imports auth plumbing and adds keyword-only auth to all bucket and bucket-file methods; stream/upload calls use resolve_request_auth(auth), resource helpers receive auth=auth.
Auth resolution unit tests and integration tests
tests/test_base_client.py
Adds resolve_request_auth unit tests (sentinel, None, string, non-string). Introduces _AuthProbe, _make_probe_client with MockTransport, and _AUTH_OVERRIDE_CASES to verify correct auth forwarding and overriding for BaseClient helpers and AuthClient public methods.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 Hop, hop, override!
Each method gets an auth to guide,
No more one-size-fits-all decree—
Pass a tuple, string, or None with glee.
The rabbit signs each request with care,
USE_CLIENT_DEFAULT if you dare! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: support overriding authentication per request' accurately and concisely describes the main feature added across the changeset, which is per-request authentication overrides in the client library.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/per-request-auth-override

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@tada5hi tada5hi requested a review from pbrassel June 23, 2026 08:33

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
flame_hub/_base_client.py (1)

9-10: 📐 Maintainability & Code Quality | 🔵 Trivial

Use public httpx.USE_CLIENT_DEFAULT instead of importing from private httpx._client.

httpx._client is unsupported private API (per httpx maintainers). Replace from httpx._client import USE_CLIENT_DEFAULT, UseClientDefault with from httpx import USE_CLIENT_DEFAULT. For the UseClientDefault type, use type(httpx.USE_CLIENT_DEFAULT) or define a local type alias to avoid depending on unstable internal exports.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@flame_hub/_base_client.py` around lines 9 - 10, Replace the import statement
that imports USE_CLIENT_DEFAULT and UseClientDefault from the private
httpx._client module with an import of USE_CLIENT_DEFAULT from the public httpx
module. For the UseClientDefault type annotation, use
type(httpx.USE_CLIENT_DEFAULT) to get the type dynamically, or alternatively
define a local type alias to avoid depending on the unstable private API. Update
all references throughout the file to use the public imports instead of the
private ones.
tests/test_base_client.py (1)

277-283: 📐 Maintainability & Code Quality | 🔵 Trivial

Add httpx.BasicAuth and tuple auth override cases to _AUTH_OVERRIDE_CASES.

The accepted contract includes (username, password) tuples and httpx.BasicAuth overrides, but the integration matrix currently covers only sentinel/string/_StaticAuthorization/None. Extending this matrix would exercise these cases end-to-end across all six parametrized test functions that use _AUTH_OVERRIDE_CASES, ensuring the request-helper and public-method forwarding paths properly handle basic auth.

Proposed matrix expansion
+import base64
 import httpx
 ...
+_BASIC_EXPECTED = "Basic " + base64.b64encode(b"user:pass").decode()
 _AUTH_OVERRIDE_CASES = [
     (httpx.USE_CLIENT_DEFAULT, "Bearer DEFAULT"),  # default sentinel keeps the client's bound auth
     ("Bearer OVERRIDE", "Bearer OVERRIDE"),  # raw header value
     (_StaticAuthorization("Bearer VIA_AUTH"), "Bearer VIA_AUTH"),  # httpx.Auth instance
+    (httpx.BasicAuth("user", "pass"), _BASIC_EXPECTED),  # httpx.Auth basic override
+    (("user", "pass"), _BASIC_EXPECTED),  # tuple basic override
     (None, None),  # disable auth for this request (no Authorization header)
 ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_base_client.py` around lines 277 - 283, The `_AUTH_OVERRIDE_CASES`
list is missing test coverage for two supported authentication forms. Extend the
`_AUTH_OVERRIDE_CASES` tuple list to include test cases for httpx.BasicAuth
instances and (username, password) tuple overrides. For the httpx.BasicAuth
case, create an instance with test credentials and include the expected
Base64-encoded Authorization header value. For the tuple case, provide a
(username, password) tuple and include its expected Basic auth header
representation. This will ensure the parametrized test functions that use
`_AUTH_OVERRIDE_CASES` exercise these authentication methods end-to-end across
the request-helper and public-method forwarding paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@flame_hub/_core_client.py`:
- Around line 878-884: The delete request paths at lines 878 and 1202 use
absolute paths starting with "/" (e.g., "/analysis-node-logs"), which is
inconsistent with other HTTP calls in the file that use relative paths (e.g.,
"master-images/command"). Remove the leading "/" from both delete request path
strings in the _client.delete calls to make them consistent with the relative
path style used throughout the rest of the file.

In `@flame_hub/_storage_client.py`:
- Around line 119-123: The stream response handler in the context manager does
not check the response status code before yielding bytes, allowing error
responses (401, 403, etc.) to be returned as file content instead of raising an
error. Add a status code check immediately after the stream context manager is
entered (after the with statement for `self._client.stream()`) to verify the
response has a successful status code (2xx range), and raise an appropriate
exception if the status indicates an error. This same fix needs to be applied to
both occurrences of this pattern, including the one at lines 181-185.

---

Nitpick comments:
In `@flame_hub/_base_client.py`:
- Around line 9-10: Replace the import statement that imports USE_CLIENT_DEFAULT
and UseClientDefault from the private httpx._client module with an import of
USE_CLIENT_DEFAULT from the public httpx module. For the UseClientDefault type
annotation, use type(httpx.USE_CLIENT_DEFAULT) to get the type dynamically, or
alternatively define a local type alias to avoid depending on the unstable
private API. Update all references throughout the file to use the public imports
instead of the private ones.

In `@tests/test_base_client.py`:
- Around line 277-283: The `_AUTH_OVERRIDE_CASES` list is missing test coverage
for two supported authentication forms. Extend the `_AUTH_OVERRIDE_CASES` tuple
list to include test cases for httpx.BasicAuth instances and (username,
password) tuple overrides. For the httpx.BasicAuth case, create an instance with
test credentials and include the expected Base64-encoded Authorization header
value. For the tuple case, provide a (username, password) tuple and include its
expected Basic auth header representation. This will ensure the parametrized
test functions that use `_AUTH_OVERRIDE_CASES` exercise these authentication
methods end-to-end across the request-helper and public-method forwarding paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3637f1ab-429a-4c86-9103-830d151d08aa

📥 Commits

Reviewing files that changed from the base of the PR and between b425f76 and c2f252b.

📒 Files selected for processing (7)
  • README.md
  • flame_hub/_auth_client.py
  • flame_hub/_base_client.py
  • flame_hub/_core_client.py
  • flame_hub/_storage_client.py
  • flame_hub/types.py
  • tests/test_base_client.py

Comment thread flame_hub/_core_client.py
Comment thread flame_hub/_storage_client.py
Stream methods now check the response status and raise HubAPIError before
yielding bytes, so an error response (e.g. from auth=None or an invalid
per-request override) is no longer returned as file content.

Also drop the leading slash from the two direct delete request paths for
consistency with the relative paths used elsewhere in the core client.

Addresses review feedback on PR #115.
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.

3 participants