Skip to content

[PRE-368] Add token validation into the Python SDK startup - #17

Merged
Siutan merged 5 commits into
mainfrom
pre-368-add-token-validation-into-the-python-sdk-startup
Jul 1, 2026
Merged

Siutan merged 5 commits into
mainfrom
pre-368-add-token-validation-into-the-python-sdk-startup

Conversation

@Siutan

@Siutan Siutan commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

This PR adds API token validation during SDK startup by calling the /api/v1/ping endpoint before workers are initialized. Invalid or expired tokens now fail fast with a PrefactorAuthError during initialize() rather than surfacing later during runtime requests.

Summary by CodeRabbit

  • New Features

    • Added access token validation during client initialization via a ping request.
  • Bug Fixes

    • Client now fails early with a clear authentication error when token validation fails.
    • Improved initialization cleanup to properly close the HTTP client on validation errors.
  • Tests

    • Added coverage for successful token validation and auth-failure cases.
    • Updated related integration/middleware/session tests to mock token validation.
  • Chores

    • Updated build/publish tasks to clean dist/ and only publish package versions if missing.
    • Updated ignore rules by removing the uv.lock ignore entry.

Validate credentials against /api/v1/ping during initialize() so invalid or expired tokens fail fast before workers start.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jun 24, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

PrefactorHttpClient now validates tokens via /api/v1/ping, PrefactorCoreClient.initialize() calls that validation before continuing, related tests and stubs were updated, package versions and release tasks were adjusted, and .gitignore no longer excludes uv.lock.

Changes

Token validation during initialization

Layer / File(s) Summary
HTTP token validation contract
packages/http/src/prefactor_http/client.py, packages/http/tests/test_client.py
PrefactorHttpClient.validate_token() sends GET /api/v1/ping, returns the parsed response, and is covered by success and 401 tests.
Core initialization validates token
packages/core/src/prefactor_core/client.py, packages/core/tests/test_agent_instance_finish_status.py, packages/core/tests/test_agent_instance_register.py, packages/core/tests/test_sdk_header.py, packages/langchain/tests/test_middleware.py, packages/livekit/tests/test_session.py
PrefactorCoreClient.initialize() awaits token validation after opening the HTTP client, and the success-path stubs and patched test flows now provide validate_token().
Token validation failure handling
packages/core/tests/test_failure_handling.py
The HTTP stub can raise a configured token-validation error, and the new failure test asserts initialize() raises PrefactorAuthError before executor creation.

Release metadata updates

Layer / File(s) Summary
Package versions and dependency
packages/core/pyproject.toml, packages/core/src/prefactor_core/_version.py, packages/http/src/prefactor_http/_version.py
packages/core requires prefactor-http>=0.1.5, and the core and HTTP version constants are bumped to 0.2.7 and 0.1.5.

Build and publish tasks

Layer / File(s) Summary
Clean build outputs
mise.toml
[tasks.build].run removes existing dist/prefactor_*.whl and dist/prefactor_*.tar.gz files before running package builds.
Conditional publish scripts
mise.toml
[tasks.publish].run and [tasks.publish-test].run now extract package versions, check whether each version already exists, and only call uv publish when the target release is missing.

Lockfile ignore rule

Layer / File(s) Summary
Remove uv.lock ignore
.gitignore
The .gitignore entry for uv.lock is deleted while the surrounding uv section remains.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • prefactordev/python-sdk#9: Both PRs touch the client initialization pipeline, including PrefactorCoreClient.initialize() and HTTP client setup/test paths.

Suggested reviewers: joshgillies

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.00% 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 clearly matches the main change: adding API token validation during Python SDK startup.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pre-368-add-token-validation-into-the-python-sdk-startup

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

@Siutan Siutan changed the title [PRE-368] add token validation into the python sdk startup [PRE-368] Add token validation into the Python SDk startup Jun 24, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
@Siutan
Siutan marked this pull request as ready for review June 25, 2026 03:15

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/tests/test_failure_handling.py (1)

394-401: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an explicit cleanup assertion for failed initialize() path (Line 401).

This test currently verifies fail-fast auth behavior but not HTTP-context teardown after validation failure. Please assert __aexit__/close behavior so this leak path is covered.

🤖 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 `@packages/core/tests/test_failure_handling.py` around lines 394 - 401, The
failed initialize() test only checks the auth error and executor state, but it
does not verify that the HTTP context is torn down after validation fails.
Update the PrefactorCoreClient initialize() failure test to explicitly assert
the cleanup path by checking the stub HTTP context’s __aexit__ / close behavior
after await client.initialize() raises, using the existing PrefactorCoreClient,
initialize(), and close() flow.
🤖 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 `@packages/core/src/prefactor_core/client.py`:
- Around line 145-146: The `initialize()` flow in `PrefactorCoreClient` leaks
the entered HTTP context when `validate_token()` fails because `_initialized` is
never set and `close()` is skipped. Wrap the `self._http.validate_token()` call
in `try/except`, and on failure invoke `self._http.__aexit__()` to clean up the
context before re-raising. Also clear the `_http` reference so the client does
not retain a half-initialized context after the exception.

---

Nitpick comments:
In `@packages/core/tests/test_failure_handling.py`:
- Around line 394-401: The failed initialize() test only checks the auth error
and executor state, but it does not verify that the HTTP context is torn down
after validation fails. Update the PrefactorCoreClient initialize() failure test
to explicitly assert the cleanup path by checking the stub HTTP context’s
__aexit__ / close behavior after await client.initialize() raises, using the
existing PrefactorCoreClient, initialize(), and close() flow.
🪄 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: c5b07b1d-d41a-4b9d-b006-8c608cfcc8e9

📥 Commits

Reviewing files that changed from the base of the PR and between 4cc3215 and 08ae4c9.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (10)
  • .gitignore
  • packages/core/src/prefactor_core/client.py
  • packages/core/tests/test_agent_instance_finish_status.py
  • packages/core/tests/test_agent_instance_register.py
  • packages/core/tests/test_failure_handling.py
  • packages/core/tests/test_sdk_header.py
  • packages/http/src/prefactor_http/client.py
  • packages/http/tests/test_client.py
  • packages/langchain/tests/test_middleware.py
  • packages/livekit/tests/test_session.py
💤 Files with no reviewable changes (1)
  • .gitignore

Comment thread packages/core/src/prefactor_core/client.py Outdated
@Siutan Siutan changed the title [PRE-368] Add token validation into the Python SDk startup [PRE-368] Add token validation into the Python SDK startup Jun 25, 2026
@Siutan
Siutan merged commit 62e8d0e into main Jul 1, 2026
11 of 12 checks passed

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 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 `@mise.toml`:
- Around line 65-68: In the publish flow, the package-index check is too
permissive because the current `curl -sf` path in the PyPI/TestPyPI existence
check treats missing packages and transport/server failures the same, which can
incorrectly fall through to `uv publish`. Update the logic around that check to
inspect the HTTP status explicitly, skip publishing only when the response is
200, and abort the run for any other status or request failure in both the PyPI
and TestPyPI branches.
🪄 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: 1dc609bf-c86f-4cd5-a248-e11bec61fd7f

📥 Commits

Reviewing files that changed from the base of the PR and between 610c781 and e0fcc09.

📒 Files selected for processing (1)
  • mise.toml

Comment thread mise.toml
Comment on lines +65 to +68
if curl -sf "https://pypi.org/pypi/${pypi_name}/${version}/json" >/dev/null; then
echo "${pypi_name} ${version} already on PyPI, skipping"
return 0
fi

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,180p' mise.toml

Repository: prefactordev/python-sdk

Length of output: 4271


🌐 Web query:

uv publish --check-url duplicate version behavior PyPI JSON endpoint curl -sf 404 transient failure

💡 Result:

When using uv publish, the --check-url option is designed to verify an index for existing files to avoid redundant uploads or to recover from failed/interrupted publishing attempts [1][2][3]. Behavior with Duplicate Versions: When --check-url is provided, uv queries the index before uploading [4]. If a file with the same name and identical content (hash match) already exists on the index, uv skips the upload [3][4]. If a file with the same name exists but the content (hash) differs, uv errors out to prevent inconsistent package releases [4]. If the upload process itself subsequently errors (e.g., due to a network issue), uv will re-check the index URL to determine if the failure was a race condition caused by a parallel upload of the same file, handling these scenarios gracefully [3][4]. Transient Failures and 404s: While uv includes retry mechanisms for transient upload failures [5][6], issues related to 404 responses during the check-url phase often stem from index-specific behaviors rather than transient network errors. For instance, some indexes (like certain GitLab configurations) may return 404s due to token permission issues or specific path handling when querying for packages [7]. Additionally, there have been reported cases where --check-url fails if the index returns unexpected content types (e.g., text/plain) for a 404 response when a package does not exist, rather than the expected JSON or HTML format [8]. Note on Authentication: A known limitation is that credentials (username/password) provided for the main --publish-url are not automatically used for the --check-url request [9]. If the index requires authentication to check for existing packages, you must explicitly include those credentials in the --check-url itself (e.g., --check-url=https://user:pass@registry.example.com/simple) [9].

Citations:


Fail closed when the package-index check is inconclusive. curl -sf treats 404, 5xx, and network/TLS failures the same, so a failed check falls through to uv publish. Check the status code explicitly, skip only on 200, and abort on anything else. Same for the TestPyPI branch.

🤖 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 `@mise.toml` around lines 65 - 68, In the publish flow, the package-index check
is too permissive because the current `curl -sf` path in the PyPI/TestPyPI
existence check treats missing packages and transport/server failures the same,
which can incorrectly fall through to `uv publish`. Update the logic around that
check to inspect the HTTP status explicitly, skip publishing only when the
response is 200, and abort the run for any other status or request failure in
both the PyPI and TestPyPI branches.

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