fix(artifact): restore collection-level permission fallback for child read/write ops - #1040
Conversation
… read/write ops A user holding a sufficient permission on a PARENT collection (e.g. a model-zoo reviewer with "rw+") was denied edit/commit/put_file on a CHILD artifact whose own config.permissions listed only its uploader (bioimage-io/tough-lion). Root cause: the parent-collection fallback in _get_artifact_with_permission was hardcoded to a read-only operation allow-list, so write ops skipped the parent check and fell through to the workspace-scope check only — which a collection-scoped reviewer does not satisfy. This regressed at 3cea1bd ("Support terminal worker"), which narrowed the previously-blanket parent fallback (16430e8) to read ops. Fix: gate the parent fallback on the required permission LEVEL instead of a hardcoded op list — allow it for any non-admin operation (read AND read_write: edit, commit, put_file, remove_file, discard_changes, ...), including staged/versionless children. delete/reset_stats/publish/get_secret map to UserPermission.admin and are excluded, so delete stays owner/admin-only and cannot be granted through a collection-level permission. The parent check validates the parent's own ACL, so no cross-workspace leak. Adds tests/test_artifact.py::test_collection_permission_fallback_for_children (real two-user integration test): reviewer with collection rw+ can edit a committed child + edit/put_file/commit a staged child; delete is denied; a read-only (r) reviewer is denied edit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for this — I dug into the failing CI and the security model, and I want to lay out precisely what's going on so we can decide the right path together. The CI failure is a real semantic conflict, not a flakeThe red build fails at Your new test Crucially, The diff is safe on some axes but reverses a documented invariant on writesCredit where due — the level-gate approach is coherent and safe on two axes I checked closely:
But it weakens the documented model on writes. Our permission model (CLAUDE.md, learned via #9) blesses only parent-read → child-read fallback ("child-read ≈ parent-read"). There is no documented parent-write → child-write fallback. This PR makes child-write ≈ parent-write for the whole collection, and it grants via plain What's needed to move forwardThis is a genuine product/security decision, not something to silently flip:
I'm holding off on merging pending that call (cc @oeway for the product decision on the reviewer-write semantics). Happy to help implement whichever direction is chosen. The branch itself rebases cleanly onto main. |
A user holding a sufficient permission on a PARENT collection (e.g. a model-zoo reviewer with "rw+") was denied edit/commit/put_file on a CHILD artifact whose own config.permissions listed only its uploader (bioimage-io/tough-lion). Root cause: the parent-collection fallback in _get_artifact_with_permission was hardcoded to a read-only operation allow-list, so write ops skipped the parent check and fell through to the workspace-scope check only — which a collection-scoped reviewer does not satisfy. This regressed at 3cea1bd ("Support terminal worker"), which narrowed the previously-blanket parent fallback (16430e8) to read ops.
Fix: gate the parent fallback on the required permission LEVEL instead of a hardcoded op list — allow it for any non-admin operation (read AND read_write: edit, commit, put_file, remove_file, discard_changes, ...), including staged/versionless children. delete/reset_stats/publish/get_secret map to UserPermission.admin and are excluded, so delete stays owner/admin-only and cannot be granted through a collection-level permission. The parent check validates the parent's own ACL, so no cross-workspace leak.
Adds tests/test_artifact.py::test_collection_permission_fallback_for_children (real two-user integration test): reviewer with collection rw+ can edit a committed child + edit/put_file/commit a staged child; delete is denied; a read-only (r) reviewer is denied edit.