You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Request a workspace-issued SAS for the job's actual linked container on first use.
Cache and revalidate that SAS for HTTPS, container identity, the backend's fixed attachment capabilities (r, w, and l), start time, and expiry.
Invalidate cache use when job container details change.
Reject a refreshed URI when its storage hostname differs from the hostname stored in the job details.
Custom container names remain supported. The legacy Workspace(storage=...) connection-string path is intentionally outside this PR's scope; its deprecation will be tracked separately.
Testing
Focused attachment validation: 25 passed.
Full local suite: 127 passed, 18 skipped.
Azure Quantum Python CI for the previous revision: build 183619 passed. CI will be rerun for the final revision.
The relevant DPv2 attachment E2E in build 183473 passed upload, list, and download (34 passed, 2 skipped in the DPv2 SDK job). The broader live build had unrelated CLI and third-party failures. The attachment E2E will be rerun against the final revision.
Related
The generated job-update endpoint correction is intentionally left to #772, which regenerated the complete client with the corrected /jobs/{jobId} route.
- upload_attachment, download_attachment, and list_attachments in base_job.py were reusing the unsigned container_uri returned by job creation instead of always fetching a fresh SAS-signed URI via workspace.get_container_uri(), causing 401 NoAuthenticationInformation errors.
- build_services_jobs_update_request in the generated _operations.py used the wrong URL path segment 'jobUpdateOptions' (the request model type name) instead of 'jobs', causing workspace.update_job() to fail with 404 Not Found.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Attachment methods now target the wrong container for jobs created with a custom container name.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Fixes attachment authentication failures and the incorrect job-update endpoint.
Changes:
Refreshes SAS-signed attachment container URIs.
Corrects job PATCH requests to use /jobs/{jobId}.
Adds regression tests for both fixes.
File summaries
File
Description
base_job.py
Refreshes attachment container SAS URIs.
_operations.py
Corrects the job update route.
test_job_attachments.py
Tests attachment URI handling.
test_workspace.py
Tests the PATCH resource path.
Review details
Suppressed comments (2)
azure-quantum/azure/quantum/job/base_job.py:381
This selects the default job-{id} container rather than the container encoded in self._details.container_uri. Jobs created with a custom container_name will therefore download from the wrong location. Request the fresh SAS using self.container_name and update the test expectation accordingly.
Listing now ignores the job's actual linked container name and always targets job-{id}. This breaks list_attachments() for the supported custom-container flow in from_input_data; obtain the fresh SAS for self.container_name and cover that case in the attachment tests.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Caller-supplied containers from different storage accounts can be redirected to same-named workspace containers.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
azure-quantum/azure/quantum/job/base_job.py:387
For jobs created with from_storage_uri(..., container_uri=...) against another storage account, this re-signs only the extracted container name in the workspace's configured account. The download then reads a different container rather than the job's explicitly linked one. Preserve a usable explicit job-level URI, or restrict workspace SAS refresh to URIs known to be in workspace storage.
This loses the storage-account identity from a caller-supplied job container_uri: get_container_uri selects the workspace-linked/configured account using only the name. Consequently, list_attachments() can list an unrelated same-named container (or create and list an empty one) instead of the explicit container retained by from_storage_uri. Preserve a usable explicit URI or verify the account before refreshing its SAS through the workspace.
A usable SAS already stored in JobDetails.container_uri is never considered here: on a new Job, the cache is empty, so even an unexpired signed URI always calls workspace.get_container_uri. This contradicts the stated reuse behavior and can fail for caller-supplied/external containers even though the existing SAS is sufficient. Cache and return the stored URI when _is_attachment_container_uri_usable(container_uri) succeeds before refreshing it; update the current signed-job-URI test, which presently expects the unnecessary refresh.
Previously missed (1)
In code that hasn't changed since last review
Reuse usable stored SAS URI before refreshing container URI
This refresh is intentional. Current Dpv1 and Dpv2 Production flows store unsigned job container URIs and require workspace-linked storage, so JobDetails.container_uri is used only to identify the expected linked container and storage hostname.
The first attachment operation requests a workspace-issued SAS, and subsequent operations reuse the validated per-job cache. Caller-supplied external job containers are outside the supported scope, while explicit method-level uri overrides remain unchanged
The reason will be displayed to describe this comment to others. Learn more.
This is the inverse of what I suggested. My argument was that permission checking is unproductive — the SDK can't request permissions (BlobDetails has only containerName/blobName), so a refresh can never remedy a permission gap. The conclusion was to drop the check and let storage answer authoritatively. Instead the check became a stricter, global precondition that fails harder. test_upload_attachment_rejects_refreshed_uri_without_full_attachment_permissions now pins rl-rejection as intended behavior.
Suggestion: validate only what a refresh can actually fix — sig present and not near expiry (the st handling is a genuinely good addition, keep it). Let a permission shortfall surface as the storage service's own 403, which names the real cause.
The reason will be displayed to describe this comment to others. Learn more.
addressed. I removed the permission checking entirely + sig, HTTPS, hostname and path validation. The cache now checks only SAS expiry. A permission shortfall now surfaces as storage's own error instead of sdk precondition
The reason will be displayed to describe this comment to others. Learn more.
Indeed so. I checked again- the refreshed sas is only stored in a private per-job cache and is never written back to job.details.container_uri. Updated in recent commit
The reason will be displayed to describe this comment to others. Learn more.
_get_attachment_container_identity hardcodes f"/job-{self.id}", which is a third copy of the job-{id} convention (also in container_name and workspace.get_container_uri's container_name_format)
The reason will be displayed to describe this comment to others. Learn more.
I removed _get_attachment_container_identity() completely. The cache is now keyed on the existing container_name property, so there is no separate job-{id} formatting duplicated for the cache
The reason will be displayed to describe this comment to others. Learn more.
I removed that. I confirmed with backend that dpv2 production and all sas-issuing endpoints validate the account name against the workspace's linked storage account server-side, so this check was indeed redundant for the linked-storage flows
The reason will be displayed to describe this comment to others. Learn more.
Done! The cache reuse check (renamed to _is_attachment_container_uri_unexpired) now validated only se expiry with the 5 min buffer.
sig, st and permissions are not checked anymore
The reason will be displayed to describe this comment to others. Learn more.
Wrong-account/ HTTP: Not reachable through this code path. Workspace.get_container_uri()'s signiture is (job-id,contianer_name, container_name_format). It never reads a hostname and resolves to exactlyone account (self.storage) on the Workspace instance), confimed by test_cache_reuse_after_hostname_mutation_never_queries_by_hostname. Backend-issued sas URIs are also always built from BlobServiceClient / BlobContainerClient tied to the account's https:// blob endpoint so an http:// response isnt something the backend can structurally return for this flow.
Unsigned / insufficient-permission accepted: Not an oversight. Per feedback - agreed to narrow validation to the one condition a refresh can fix (expiry) and defer signature/permission enforcement to Blob Storage's own authorative response. Backend-issued tokens are always signed with full permissions in practice, so this only affects synthetic/malformed inputs, which several tests exercise to document the pass-through behavior
Azure Pipelines:
Successfully started running 1 pipeline(s).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes job attachment operations failing after submission because the service stores an unsigned container URI.
upload_attachment,download_attachment, andlist_attachmentsnow:r,w, andl), start time, and expiry.Custom container names remain supported. The legacy
Workspace(storage=...)connection-string path is intentionally outside this PR's scope; its deprecation will be tracked separately.Testing
25 passed.127 passed, 18 skipped.34 passed, 2 skippedin the DPv2 SDK job). The broader live build had unrelated CLI and third-party failures. The attachment E2E will be rerun against the final revision.Related
The generated job-update endpoint correction is intentionally left to #772, which regenerated the complete client with the corrected
/jobs/{jobId}route.