Skip to content

feat(application): read shared runs via --share-token - #688

Merged
olivermeyer merged 6 commits into
mainfrom
feat/PYSDK-145-read-run-with-share-token
Aug 6, 2026
Merged

feat(application): read shared runs via --share-token#688
olivermeyer merged 6 commits into
mainfrom
feat/PYSDK-145-read-run-with-share-token

Conversation

@dima-aignostics

@dima-aignostics dima-aignostics commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Why?
Enable an authenticated user who holds a share-token secret to read an application run shared with them via the CLI (PYSDK-145, UC2 token-based sharing). OAuth login remains required — the share token is additive, elevating the authenticated user's access to a run they could not otherwise read. Follow-up to PYSDK-132; design per ADR-PAPI-0004 (token forwarded as a share_token query parameter alongside the OAuth Bearer).

How?
Add an optional --share-token option to run describe, run dump-metadata, run dump-item-metadata, and run result download, threading it through Service into Run/Artifact where it is forwarded URL-encoded as the share_token query parameter on the run, items, and artifact-file requests, and folded into the operation-cache key so share-token reads stay isolated from authenticated reads of the same run. A 403 propagates unchanged through the download path (rather than being wrapped into RuntimeError) so the CLI surfaces a token-omitting "access denied" message and exits 1; omitting the flag is a pure no-op passthrough.

@dima-aignostics
dima-aignostics requested a review from a team as a code owner June 22, 2026 08:46
@dima-aignostics
dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch 4 times, most recently from b524be7 to 9510e92 Compare June 22, 2026 11:36
@dima-aignostics
dima-aignostics force-pushed the feat/PYSDK-132-add-run-sharing-to-python-sdk branch 6 times, most recently from 6ae872e to 0bc4980 Compare June 23, 2026 21:15
Base automatically changed from feat/PYSDK-132-add-run-sharing-to-python-sdk to main June 29, 2026 08:04
@dima-aignostics
dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch 3 times, most recently from 5ab4c44 to 23c6793 Compare June 30, 2026 14:04
@codecov

codecov Bot commented Jun 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.00000% with 3 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/aignostics/application/_cli.py 91.30% 1 Missing and 1 partial ⚠️
src/aignostics/application/_utils.py 80.00% 0 Missing and 1 partial ⚠️
Files with missing lines Coverage Δ
src/aignostics/application/_service.py 64.06% <100.00%> (+0.25%) ⬆️
src/aignostics/platform/resources/runs.py 86.48% <100.00%> (+0.96%) ⬆️
src/aignostics/application/_utils.py 88.66% <80.00%> (-0.22%) ⬇️
src/aignostics/application/_cli.py 79.43% <91.30%> (+1.21%) ⬆️

... and 1 file with indirect coverage changes

@dima-aignostics
dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 23c6793 to c3c99ef Compare June 30, 2026 15:38
@dima-aignostics dima-aignostics changed the title feat(application): add --share-token to run describe CLI command (PYS… feat(application): add --share-token to run commands Jul 1, 2026
@dima-aignostics
dima-aignostics force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 01154f0 to 8bad631 Compare July 1, 2026 11:23
@sonarqubecloud

sonarqubecloud Bot commented Jul 1, 2026

Copy link
Copy Markdown

@olivermeyer
olivermeyer force-pushed the feat/PYSDK-145-read-run-with-share-token branch 2 times, most recently from d8936d0 to b2023b8 Compare August 5, 2026 08:55
olivermeyer added a commit that referenced this pull request Aug 5, 2026
Address code-review findings on PR #688:
- Fix two _service.py docstrings that wrongly described share-token access as
  "without OAuth"/"unauthenticated"; share tokens elevate an already
  OAuth-authenticated user's access.
- Rewrite the three forbidden CLI tests to raise ForbiddenException from the
  real source (run.details()/run.results()) instead of application_run, which
  wraps all exceptions into RuntimeError in production.
- Normalize an empty --share-token to None at the application_run choke point
  so a blank value falls back to the normal authenticated read; add service
  tests for both branches.
- Make share_token_access_denied_message a pure builder and move the warning
  log to the four CLI call sites (command-query separation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@olivermeyer
olivermeyer force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 48c83d8 to 65027bb Compare August 6, 2026 08:32
@olivermeyer olivermeyer changed the title feat(application): add --share-token to run commands feat(application): read shared runs via --share-token Aug 6, 2026

@arne-aignx arne-aignx left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM. I added two smaller nits

Comment thread src/aignostics/application/_utils.py Outdated
raise RuntimeError(message)


def share_token_access_denied_message(run_id: str, share_token: str | None) -> str:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: run_access_denied_message might be a better wording here.
I was a bit confused reading through the initial code wondering "Why do we provide a share_token related error message, when a 403 is returned by the API and no share token was provided

if self._share_token is not None:
# Percent-encode the secret so reserved characters (& # = space) cannot
# corrupt the URL or inject extra query parameters.
endpoint_url += f"?{urlencode({'share_token': self._share_token})}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nit: Alternatively, self._share_token could also be forwarded to _fetch_redirect_url as an argument, and we let requests.get handle the URL construction from the provided query paramters

@olivermeyer
olivermeyer enabled auto-merge (squash) August 6, 2026 09:45
dima-aignostics and others added 3 commits August 6, 2026 11:50
…DK-145)

Recipients holding a share token secret can now describe a run without
OAuth login by passing --share-token <secret> to `application run describe`.
The token is used directly as the Bearer token for platform API requests.

- Adds `--share-token` option to `run describe`; when set, creates a
  `Client(token_provider=…)` bypassing OAuth, with `hide_platform_queue_position=True`
- Catches `UnauthorizedException` and `ForbiddenException` when using a share
  token and surfaces a clear "Access denied" message with exit code 1
- Adds 5 integration tests covering success (text + JSON), not-found,
  unauthorized, and forbidden paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds a --share-token option to `application run describe / dump-metadata /
dump-item-metadata / result download` (PYSDK-145), granting an authenticated
user access to a run that has been shared with them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
olivermeyer and others added 3 commits August 6, 2026 11:51
Address code-review findings on PR #688:
- Fix two _service.py docstrings that wrongly described share-token access as
  "without OAuth"/"unauthenticated"; share tokens elevate an already
  OAuth-authenticated user's access.
- Rewrite the three forbidden CLI tests to raise ForbiddenException from the
  real source (run.details()/run.results()) instead of application_run, which
  wraps all exceptions into RuntimeError in production.
- Normalize an empty --share-token to None at the application_run choke point
  so a blank value falls back to the normal authenticated read; add service
  tests for both branches.
- Make share_token_access_denied_message a pure builder and move the warning
  log to the four CLI call sites (command-query separation).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@olivermeyer
olivermeyer force-pushed the feat/PYSDK-145-read-run-with-share-token branch from 99f4bc6 to cd81e88 Compare August 6, 2026 11:02
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

@olivermeyer
olivermeyer merged commit 69122cc into main Aug 6, 2026
24 checks passed
@olivermeyer
olivermeyer deleted the feat/PYSDK-145-read-run-with-share-token branch August 6, 2026 11:39
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