feat: support permissions in DriveInstance create/update (ENG-2761)#177
feat: support permissions in DriveInstance create/update (ENG-2761)#177devin-ai-integration[bot] wants to merge 6 commits into
Conversation
…2761) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Replace manual test with proper pytest integration test in tests/integration/core/sandbox/test_drive_acl.py following the existing TestDriveOperations pattern. Covers all 9 ACL scenarios: open-access, label-match, label-mismatch, read-only, OR logic, AND logic, path scoping, update permissions, and wildcard permission. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Add permissions field to DriveCreateConfiguration - Pass permissions through create() for both async and sync variants - Include permissions in update merge logic for _update_drive_by_name and _update_drive_by_name_sync (config, dict, and Drive inputs) - Add permissions property to DriveInstance and SyncDriveInstance - Import DrivePermission and Unset in drive.py - Add 15 unit tests covering create, update, and property access Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
✅ Linked to Linear issue ENG-2761 — status already In Progress
Note Posted by Linear Issue Enforcer · Tag @mendral-app with feedback. |
🔀 Interaction Flow: Drive Permissions SupportsequenceDiagram
participant User as User Code
participant Config as DriveCreateConfiguration
participant Instance as DriveInstance / SyncDriveInstance
participant Spec as DriveSpec
participant Client as API Client (Generated)
participant API as Backend API
%% Create Flow
Note over User,API: Create Drive with Permissions
User->>Config: new(name, permissions=[DrivePermission(...)])
Config->>Config: from_dict() extracts permissions
User->>Instance: create(config)
Instance->>Spec: DriveSpec(permissions=config.permissions or UNSET)
Instance->>Client: create_drive(body=Drive(spec=Spec))
Client->>API: POST /drives {spec: {permissions: [...]}}
API-->>Client: Drive response
Client-->>Instance: Drive model
Instance-->>User: DriveInstance (with .permissions property)
%% Update Flow
Note over User,API: Update Drive Permissions
User->>Instance: update(drive_name, new_config)
Instance->>Client: get_drive(drive_name)
Client-->>Instance: current Drive state
Instance->>Instance: Merge: new permissions if set,<br/>else preserve existing
Instance->>Spec: DriveSpec(permissions=merged)
Instance->>Client: update_drive(body=Drive(spec=Spec))
Client->>API: PUT /drives/{name} {spec: {permissions: [...]}}
API-->>Client: Updated Drive
Client-->>Instance: Drive model
Instance-->>User: DriveInstance
SummaryThis PR adds per-drive ACL permission support through the SDK wrapper layer:
Key design decisions:
Note Posted by PR Sequence Diagram · Tag @mendral-app with feedback. |
…rve empty list An explicit permissions=[] should be sent as an empty list (clear permissions), not converted to UNSET (omit field). Fixes all 4 occurrences in create/update paths for both async and sync variants. Adds test for empty-list case. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Needs attention — 3 issues across 2 files
The or UNSET bug in drive.py create paths is fixed (commit 60a138c), but the same empty-list falsy bug remains in two other places: the update merge conditions at lines 607 and 685 use new_spec.permissions as a truthiness check, which treats [] the same as UNSET. The drive_spec.py from_dict issue from the previous review also remains unfixed.
Prompt for AI agents (all issues)
Check if these issues are valid — if so, understand the root cause of each and fix them.
<assessment>
The `or UNSET` bug in `drive.py` create paths is fixed (commit 60a138c), but the same empty-list falsy bug remains in two other places: the update merge conditions at lines 607 and 685 use `new_spec.permissions` as a truthiness check, which treats `[]` the same as UNSET. The `drive_spec.py` `from_dict` issue from the previous review also remains unfixed.
</assessment>
<file name="src/blaxel/core/drive/drive.py">
<issue location="src/blaxel/core/drive/drive.py:606">
`new_spec.permissions` is falsy when `[]`, so explicitly passing `permissions=[]` to clear permissions falls through to the else branch, preserving old permissions instead. Same fix pattern as commit 60a138c should apply here.
</issue>
<issue location="src/blaxel/core/drive/drive.py:684">
Same empty-list falsy bug in the sync variant of update merge logic.
</issue>
</file>
<file name="src/blaxel/core/client/models/drive_spec.py">
<issue location="src/blaxel/core/client/models/drive_spec.py:77">
(Unaddressed from previous review) `permissions` is initialized to `[]` unconditionally; when `_permissions` is UNSET (key absent from dict), `from_dict` produces `permissions=[]` instead of preserving UNSET, changing serialization on round-trips. This is auto-generated code so it may need to be fixed upstream in the generator.
</issue>
</file>
Tag @mendral-app with feedback or questions. View session
| permissions=new_spec.permissions | ||
| if new_spec and new_spec.permissions and not isinstance(new_spec.permissions, Unset) | ||
| else (current_drive.spec.permissions if current_drive.spec else UNSET), |
There was a problem hiding this comment.
bug (P2): new_spec.permissions is falsy when [], so explicitly passing permissions=[] to clear permissions falls through to the else branch, preserving old permissions instead. Same fix pattern as commit 60a138c should apply here.
Suggested change
| permissions=new_spec.permissions | |
| if new_spec and new_spec.permissions and not isinstance(new_spec.permissions, Unset) | |
| else (current_drive.spec.permissions if current_drive.spec else UNSET), | |
| permissions=new_spec.permissions | |
| if new_spec and not isinstance(new_spec.permissions, Unset) | |
| else (current_drive.spec.permissions if current_drive.spec else UNSET), |
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/blaxel/core/drive/drive.py, line 606:
<issue>
`new_spec.permissions` is falsy when `[]`, so explicitly passing `permissions=[]` to clear permissions falls through to the else branch, preserving old permissions instead. Same fix pattern as commit 60a138c should apply here.
</issue>
There was a problem hiding this comment.
Valid — the and new_spec.permissions truthiness check here also treats [] as falsy. Will fix by removing that condition and keeping only not isinstance(new_spec.permissions, Unset).
| permissions=new_spec.permissions | ||
| if new_spec and new_spec.permissions and not isinstance(new_spec.permissions, Unset) | ||
| else (current_drive.spec.permissions if current_drive.spec else UNSET), |
There was a problem hiding this comment.
bug (P2): Same empty-list falsy bug in the sync variant of update merge logic.
Suggested change
| permissions=new_spec.permissions | |
| if new_spec and new_spec.permissions and not isinstance(new_spec.permissions, Unset) | |
| else (current_drive.spec.permissions if current_drive.spec else UNSET), | |
| permissions=new_spec.permissions | |
| if new_spec and not isinstance(new_spec.permissions, Unset) | |
| else (current_drive.spec.permissions if current_drive.spec else UNSET), |
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/blaxel/core/drive/drive.py, line 684:
<issue>
Same empty-list falsy bug in the sync variant of update merge logic.
</issue>
There was a problem hiding this comment.
Same fix needed here as the async variant above.
| permissions = [] | ||
| _permissions = d.pop("permissions", UNSET) | ||
| for permissions_item_data in _permissions or []: | ||
| permissions_item = DrivePermission.from_dict(permissions_item_data) | ||
|
|
||
| permissions.append(permissions_item) |
There was a problem hiding this comment.
bug (P3), medium confidence: (Unaddressed from previous review) permissions is initialized to [] unconditionally; when _permissions is UNSET (key absent from dict), from_dict produces permissions=[] instead of preserving UNSET, changing serialization on round-trips. This is auto-generated code so it may need to be fixed upstream in the generator.
Suggested change
| permissions = [] | |
| _permissions = d.pop("permissions", UNSET) | |
| for permissions_item_data in _permissions or []: | |
| permissions_item = DrivePermission.from_dict(permissions_item_data) | |
| permissions.append(permissions_item) | |
| _permissions = d.pop("permissions", UNSET) | |
| permissions: Union[Unset, list["DrivePermission"]] = UNSET | |
| if not isinstance(_permissions, Unset): | |
| for permissions_item_data in _permissions or []: | |
| if isinstance(permissions, Unset): | |
| permissions = [] | |
| permissions_item = DrivePermission.from_dict(permissions_item_data) | |
| permissions.append(permissions_item) |
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/blaxel/core/client/models/drive_spec.py, line 77:
<issue>
(Unaddressed from previous review) `permissions` is initialized to `[]` unconditionally; when `_permissions` is UNSET (key absent from dict), `from_dict` produces `permissions=[]` instead of preserving UNSET, changing serialization on round-trips. This is auto-generated code so it may need to be fixed upstream in the generator.
</issue>
There was a problem hiding this comment.
Acknowledged — this is auto-generated code (client/models/) which per repo convention must not be edited manually. Should be addressed upstream in the code generator.
🧪 Testing GuideWhat this PR addressesExtends the Key additions:
Steps to exercise the new behavior
What to verify (expected behavior)
Note Posted by PR Testing Guide · Tag @mendral-app with feedback. |
Summary
Extends the
DriveInstance/SyncDriveInstancewrapper to support per-drive ACL permissions, building on the auto-generatedDrivePermissiontypes from PR #176.Changes:
DriveCreateConfiguration.__init__gainspermissions: list | None = None;from_dictextracts it.DriveInstance.create/SyncDriveInstance.createpasspermissionsintoDriveSpecfor bothDriveCreateConfigurationanddictinputs, usingis not Nonecheck (notor UNSET) to preserve explicitpermissions=[]._update_drive_by_name/_update_drive_by_name_syncincludepermissionsin both thenew_specconstruction (from config/dict) and the merge logic:permissionsproperty (drive.spec.permissions).Link to Devin session: https://app.devin.ai/sessions/730361d1c61c4cd884e912562ebefdfe
Requested by: @drappier-charles