Skip to content

fix: authenticate the client application version lookup - #18

Merged
burnedikt merged 2 commits into
mainfrom
fix/authenticate-client-application-version-lookup
Oct 6, 2026
Merged

burnedikt merged 2 commits into
mainfrom
fix/authenticate-client-application-version-lookup

Conversation

@burnedikt

@burnedikt burnedikt commented Aug 3, 2026 •

Copy link
Copy Markdown
Member

retrieve_client_application_version() was the only request in ClientApplicationApiClient that sent no Authorization header. main() uses it as the pre-flight duplicate check before an upload:

check_response = client_applications_api.retrieve_client_application_version(args.slug, args.version)
if check_response.status_code < 400:
    print(f"Version {args.version} already existing! Aborting.")
    exit(1)

Portal only serves the current version of a client application to anonymous callers, so for any version that has since been superseded the unauthenticated lookup gets a 404 and the check concludes "doesn't exist". The binary is then chunk-uploaded and the run fails on the backend's uniqueness constraint with a bare 400 — instead of aborting cleanly before doing any work.

Normal releases are unaffected either way (a genuinely new version 404s before and after). This only shows up when re-uploading a version that already exists and is no longer current — e.g. re-running a release job.

Sending the credentials the rest of the client already uses restores the clean abort. Added tests/test_client_application_uploader.py to pin that the lookup carries the header.

Context: this surfaced while auditing consumers of the client-application endpoints for Innoactive/Portal-Backend#2280, which tightens anonymous read access to superseded versions.

The branch also carries a one-line uv.lock fix: the 3.5.0 release commit bumped pyproject.toml only, so CI's uv sync --locked rejected the lockfile, which still recorded portal-client 3.4.1.

uv sync --locked passes; uv run pytest → 51 passed. ruff format --check is clean on both touched files. ruff check reports only the pre-existing exit() → sys.exit() findings (PLR1722) in main(), on lines this PR leaves untouched.

🤖 Generated with Claude Code

burnedikt and others added 2 commits October 6, 2026 13:44
The duplicate check that runs before uploading a new client application version
was the only request in this uploader without credentials. Portal only serves
the *current* version of a client application to anonymous callers, so once a
version has been superseded the unauthenticated lookup reports it as missing:
the "Version X already existing! Aborting." guard is skipped, the binary is
uploaded, and the run then fails on the backend's uniqueness constraint with a
bare 400 instead.

Refs Innoactive/Portal-Backend#2280

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The 3.5.0 release commit bumped pyproject.toml only, so `uv sync --locked` in CI
rejected the lockfile, which still recorded portal-client 3.4.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@burnedikt
burnedikt force-pushed the fix/authenticate-client-application-version-lookup branch from 3023fdd to d7e5a67 Compare October 6, 2026 11:45
@burnedikt
burnedikt merged commit ec9bab7 into main Oct 6, 2026
2 checks passed
@burnedikt
burnedikt deleted the fix/authenticate-client-application-version-lookup branch October 6, 2026 11:57
@innoactive-semantic-release

Copy link
Copy Markdown

🎉 This PR is included in version 3.6.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant