feat(application): read shared runs via --share-token - #688
Conversation
b524be7 to
9510e92
Compare
6ae872e to
0bc4980
Compare
5ab4c44 to
23c6793
Compare
Codecov Report❌ Patch coverage is
|
23c6793 to
c3c99ef
Compare
01154f0 to
8bad631
Compare
|
d8936d0 to
b2023b8
Compare
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>
48c83d8 to
65027bb
Compare
arne-aignx
left a comment
There was a problem hiding this comment.
LGTM. I added two smaller nits
| raise RuntimeError(message) | ||
|
|
||
|
|
||
| def share_token_access_denied_message(run_id: str, share_token: str | None) -> str: |
There was a problem hiding this comment.
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})}" |
There was a problem hiding this comment.
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
…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>
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>
99f4bc6 to
cd81e88
Compare
|



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_tokenquery parameter alongside the OAuth Bearer).How?
Add an optional
--share-tokenoption torun describe,run dump-metadata,run dump-item-metadata, andrun result download, threading it throughServiceintoRun/Artifactwhere it is forwarded URL-encoded as theshare_tokenquery 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 intoRuntimeError) so the CLI surfaces a token-omitting "access denied" message and exits 1; omitting the flag is a pure no-op passthrough.