Skip to content

fix(runs): authenticate 'tw runs star' and 'tw runs unstar' - #696

Merged
cristianrcv merged 1 commit into
feat/NOTASK-api-1.101-catch-upfrom
fix/NOTASK-runs-star-auth
Oct 5, 2026
Merged

cristianrcv merged 1 commit into
feat/NOTASK-api-1.101-catch-upfrom
fix/NOTASK-runs-star-auth

Conversation

@swampie

@swampie swampie commented Oct 5, 2026

Copy link
Copy Markdown
Member

Summary

tw runs star and tw runs unstar, added in #685, fail with Unauthorized against a live Platform. This stacks on that PR and fixes them.

Stack: master → #685 (API 1.101) → this PR. Base is feat/NOTASK-api-1.101-catch-up; review #685 first.

The bug

Found while testing #685 against cloud.stage-seqera.io (API 1.231.0):

$ tw runs star -i 2bzcf17WQPSw3V -w seqerakit/scidev-testing
 ERROR: Unauthorized. Check your access token, workspace id and tower server url.

The same call by hand returns 200, so it is not a permissions problem. tw -v shows the star request going out without an Authorization header, while every other request in the same invocation has one:

3 > POST https://api.cloud.stage-seqera.io/workflow/2bzcf17WQPSw3V/star?workspaceId=21810926945220
3 > Accept: application/json
3 > Content-Type: application/json
3 > User-Agent: tw/0.41.0 (java)
3 < 401

Root cause

The workflow star endpoints are missing their security requirement in the Platform OpenAPI spec, so the generated SDK passes null auth names:

SDK method authNames argument to invokeAPI
WorkflowsApi.describeWorkflow new String[]{"BearerAuth"}
WorkflowsApi.createWorkflowStar null
WorkflowsApi.deleteWorkflowStar null

ApiClient.invokeAPI then skips authentication entirely when that array is null — it guards the updateParamsForAuth call with a null check rather than falling back to the configured scheme. So the request is sent unauthenticated.

Scanning all 263 *WithHttpInfo methods in SDK 1.200.0, eleven declare no security: the three *WorkflowStar ones, six GA4GH ones, ServiceInfoApi.info and NextflowApi.nextflowVersions.

Fix

Default the auth names to BearerAuth when an operation declares none, in the ApiClient subclass AbstractApiCmd already builds. This goes through the SDK's own authentication path, reusing the token from setBearerToken.

The fix is general rather than special-casing the two star calls, so a future spec gap cannot silently send another request unauthenticated. The other nine affected operations are unaffected in practice: info and nextflowVersions are genuinely public, and the GA4GH ones target the same host the token belongs to. A token is always present by the time the client is built — AbstractApiCmd throws MissingTowerAccessTokenException otherwise.

Why CI did not catch it

The star tests matched on method and path only, so an unauthenticated request satisfied them — which is why #685 is green at 819/819. This PR asserts the Authorization header instead.

Note the test class shares one MockServer without a reset, so star requests from sibling tests are recorded too; the verification allows for those rather than pinning an exact count.

Verification

  • ./gradlew test: 821 tests, 0 failures (819 + the 2 new). checkLicenses passes.
  • Watched both new tests fail before the fix, and confirmed they still fail with the fix temporarily disabled, so they are a real regression guard.
  • Native binary against staging:
    $ tw runs star -i 2bzcf17WQPSw3V -w seqerakit/scidev-testing
      Pipeline run '2bzcf17WQPSw3V' starred at [seqerakit / scidev-testing] workspace
    Server state actually toggles — isStarred: true then false after unstar.
  • Smoke-tested info, organizations list, workspaces list, pipelines list, compute-envs list, organizations quotas, teams list, access-tokens list — the override touches every API call, and tw info in particular uses one of the previously unauthenticated endpoints.

Note for reviewers

This is a workaround, not the cure. The spec is still missing the security block in SDK 1.230.0, which the last PR in the stack bumps to — I checked, and all three star methods still pass null. The real fix belongs in tower-sdk-gencode; this override is harmless to keep afterwards and becomes a no-op.

🤖 Generated with Claude Code

Both commands failed with "Unauthorized" against a live Platform, even
though the caller's token was valid and the same request made by hand
succeeded.

The workflow star endpoints are missing their security requirement in the
Platform OpenAPI spec, so the generated SDK passes no auth names for them.
ApiClient.invokeAPI skips authentication entirely when the auth name array
is null, rather than falling back to the configured scheme, so the request
went out with no Authorization header at all.

Default the auth names to BearerAuth when an operation declares none. This
routes through the SDK's own authentication, reusing the token already set
with setBearerToken.

In SDK 1.200.0 eleven operations declare no security: the three
*WorkflowStar ones, six GA4GH ones, ServiceInfoApi.info and
NextflowApi.nextflowVersions. The last two are genuinely public and the
GA4GH ones target the same host, so sending the token is harmless; a token
is always present by the time the client is built.

The existing star tests matched on method and path only, so an
unauthenticated request satisfied them. Assert the Authorization header
instead. The mock server is shared across the test class without a reset,
so the verification allows for the star requests other tests record.

This is a workaround, not the cure: the spec is still missing the security
block in SDK 1.230.0. Once that is fixed the override becomes a no-op.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@cristianrcv
cristianrcv merged commit ed484ab into feat/NOTASK-api-1.101-catch-up Oct 5, 2026
8 checks passed
@cristianrcv
cristianrcv deleted the fix/NOTASK-runs-star-auth branch October 8, 2026 09:09
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.

2 participants