Skip to content

feat: add container-specific permissions and immutable flag#272

Open
flash7777 wants to merge 6 commits into
cs3org:mainfrom
flash7777:feature/container-permissions-and-immutable
Open

feat: add container-specific permissions and immutable flag#272
flash7777 wants to merge 6 commits into
cs3org:mainfrom
flash7777:feature/container-permissions-and-immutable

Conversation

@flash7777
Copy link
Copy Markdown

@flash7777 flash7777 commented May 27, 2026

Summary

This PR adds container-specific permissions and an immutable (freeze) attribute to the CS3 storage provider API.

New fields in ResourcePermissions

  • delete_container (field 21): delete permission for containers only, independent of file delete
  • move_container (field 22): move/rename permission for containers only, independent of file move

New attribute in ResourceInfo

  • immutable (field 20): persistent boolean attribute (xattr) — when true, resource cannot be modified/deleted/moved/renamed. For containers, also prevents creation of new children.

New RPCs in ProviderAPI

  • SetImmutable: freezes a resource (manager/admin only)
  • UnsetImmutable: unfreezes a resource (manager/admin only)

Motivation

We are developing an EDMS layer for German municipalities on top of OpenCloud/Reva. Core requirement: protecting file plan (Aktenplan) directory structures while allowing users to work freely with documents inside them.

The current API cannot express "users may delete files but not directories" — delete and move apply to both equally. And there is no persistent freeze/immutable concept (locks are temporary).

See docs/proposals/container-permissions-and-immutable.md for the full proposal.

Note on field 20

Field 20 in ResourceInfo is also targeted by #190 (Status). We have commented there to coordinate. We believe immutable and status serve different purposes (persistent admin attribute vs. transient processing state) and deserve separate fields.

Backward compatibility

All changes are additive. When new permission fields are not set, implementations fall back to existing delete/move behavior. Existing clients continue to work unchanged.

Related

flash and others added 2 commits May 27, 2026 18:35
Add two new permission fields to ResourcePermissions:
- delete_container (field 21): controls whether containers/directories
  can be deleted, independent of the file delete permission
- move_container (field 22): controls whether containers/directories
  can be moved or renamed, independent of the file move permission

Add immutable field (field 20) to ResourceInfo:
- When set, prevents modification, deletion, moving or renaming
- For containers, also prevents creation of new children
- Existing non-immutable children can still be modified

These additions enable DMS use cases such as:
- File plan (Aktenplan) structure protection
- Retention/legal hold at the resource level
- Granular permission control separating file and directory operations

The new permission fields are backward compatible: when not explicitly
set, implementations should fall back to the existing delete/move
permissions for containers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add proposal document explaining the motivation, specification, and
backward compatibility for the new delete_container, move_container,
and immutable fields.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@flash7777
Copy link
Copy Markdown
Author

Context: Why we need this

We are currently developing an EDMS (Electronic Document Management System) layer on top of OpenCloud/Reva for German municipalities and public administration (Kommunalverwaltungen).

In this domain, file plans (Aktenpläne) are a fundamental concept — rigid, hierarchical directory structures (typically 4 levels deep) that must remain stable over years or even decades. Users work within this structure daily: they create, edit, and manage documents, but the structure itself must not be accidentally (or intentionally) altered by regular users.

Today, the CS3 permission model offers no way to express this. The delete and move permissions apply equally to files and containers. An editor who can delete a misplaced PDF can also delete an entire department folder — there is no middle ground.

The three additions in this proposal — delete_container, move_container, and immutable — are small in scope but would be a significant improvement for real-world DMS and records management use cases. They allow administrators to protect directory structures while giving users full flexibility to work with documents.

We believe this benefits not just our EDMS project, but any CS3-based deployment where directory structures carry organizational meaning — universities, research institutions, enterprises, and public sector organizations alike.

We are happy to contribute the implementation work in Reva (see cs3org/reva#5628) and would appreciate feedback from the community on the proposed API design.

@flash7777
Copy link
Copy Markdown
Author

Quick note: The commits mention "Claude" as co-author — this just means we used Claude Code (AI coding assistant) as tooling support during development. The proposal and its rationale are entirely ours, based on real requirements from our EDMS project. Happy to discuss any aspect of it.

- Add immutable field (20) to ResourceInfo as persistent xattr attribute
- Add SetImmutable/UnsetImmutable RPCs to ProviderAPI
- Update proposal to clarify distinction between attribute (immutable)
  and action (SetImmutable), and how it differs from locks and status
@glpatcern
Copy link
Copy Markdown
Member

Hi @flash7777, thanks for the contribution, I can see the idea is genuine even if the text is produced by Claude.

I do think this makes very much sense. The only issue I can see in terms of implementations is how can a storage provider honor the immutable flag, for the cases (such as how we deploy Reva at CERN) where users have direct access to the storage. But ok this is kind of an implementation detail, the extended permission model could already be used without implementing the immutable RPCs.

@flash7777
Copy link
Copy Markdown
Author

Thanks for the quick feedback!

Good point about the immutable flag and direct storage access. You are right — if users can bypass Reva and access the storage directly (e.g. via EOS FUSE mount), an xattr-based immutable flag alone cannot be enforced.

A few thoughts:

  • For decomposedfs (as used by OpenCloud), users never have direct storage access, so xattr-based enforcement works reliably.
  • For EOS, the flag could potentially be mapped to EOS ACLs or the existing EOS immutable attribute. But that is indeed an implementation detail per storage driver.
  • As you said, the permission fields (delete_container, move_container) are useful independently and can be adopted without implementing the immutable RPCs at all.

Would it make sense to split this into two PRs — one for the permission fields only, and a separate one for immutable? That way the permissions can move forward without being blocked by the immutable discussion.

@flash7777
Copy link
Copy Markdown
Author

One more thought on the direct-access question: regardless of the enforcement layer, the immutable state has to live somewhere. A separate database or metastore would add complexity and synchronization issues. Storing it as an xattr directly on the resource (as Reva already does for locks, ACLs, etc.) seems like the natural fit.

For EOS with FUSE access, the storage driver could map the immutable flag to native EOS attributes (e.g. sys.acl), so FUSE would respect it too. Would it make sense to explore a complementary PR for the EOS driver? We don't have an EOS environment but would be happy to collaborate on the approach.

@glpatcern
Copy link
Copy Markdown
Member

Would it make sense to split this into two PRs

From CS3 Reva side, I'm happy to merge this as is - we'd put stubs for now on the immutable RPCs.

What others think in OpenCloud and ownCloud? @butonic @kobergj

@micbar
Copy link
Copy Markdown
Member

micbar commented May 29, 2026

I see that the community is growing and more use cases are evolving. I see no disadvantages with this change, so let’s go for it.

Refine the immutable field comment to distinguish:
- File (freeze): final, irreversible, no modification
- Container (protect): structure fixed, reversible by managers
- Self vs. parent rule: object is immutable if own or parent
  attribute is set

Add immutable-overview.md as reference specification.
No structural changes to the proto definition.
@flash7777
Copy link
Copy Markdown
Author

Pushed a documentation-only update to clarify the immutable semantics based on our EDMS experience. No structural changes to the proto — just refined comments.

Key clarifications:

  • File = freeze (irreversible, content fixed)
  • Container = protect (structure fixed, reversible by managers)
  • Self vs. parent rule: an object is immutable if its own OR its parent's attribute is set

Added docs/proposals/immutable-overview.md as a concise reference spec.

Add two permission fields to control who may set the immutable
attribute, separated by resource type:

- set_immutable_file (field 23): freeze files (irreversible)
- set_immutable_container (field 24): protect/unprotect containers
  (reversible by managers)

This separation allows roles to grant container protection rights
without granting the ability to irreversibly freeze files.
@flash7777
Copy link
Copy Markdown
Author

Added two permission fields for controlling who may set the immutable attribute:

  • set_immutable_file (field 23): freeze files — this is irreversible, so it needs to be granted carefully
  • set_immutable_container (field 24): protect/unprotect containers — reversible, suitable for space managers

This follows the same pattern as delete/delete_container and move/move_container: separating file and container operations so roles can be configured precisely. A space manager may protect directory structures without being able to permanently freeze files, or vice versa.

flash7777 pushed a commit to flash7777/reva that referenced this pull request May 30, 2026
Add xattr-based immutable (freeze/protect) support:

Storage:
- New xattr: user.oc.immutable
- ImmutableState enum: None, Protected (parent), Frozen (self)

Node methods:
- IsImmutable(): check self attribute
- GetImmutableState(): effective state (self or parent)
- FreezeFile(): set immutable on file (irreversible)
- ProtectContainer(): set immutable on container (reversible)
- UnprotectContainer(): remove immutable from container

Handler checks (Delete, Move, CreateDir, Upload):
- Frozen/protected resources cannot be deleted or moved
- Protected containers reject new children and modifications
- Frozen files reject overwrite

TODO markers for delete_container/move_container (cs3org/cs3apis#272).
flash7777 pushed a commit to flash7777/reva that referenced this pull request May 30, 2026
Port cs3org/cs3apis#272 via forked go-cs3apis with new fields:
- DeleteContainer, MoveContainer (ResourcePermissions fields 21-22)
- SetImmutableFile, SetImmutableContainer (fields 23-24)
- Immutable (ResourceInfo field 20)

Changes:
- go.mod: replace cs3org/go-cs3apis with flash7777/go-cs3apis fork
- role.go: Editor/SpaceEditor/Manager/Coowner get DeleteContainer
  and MoveContainer; Manager/Coowner get SetImmutable permissions
- decomposedfs.go: replace TODO markers with real DeleteContainer
  and MoveContainer checks in Delete/Move handlers
- grants.go: ACL encoding/decoding for +dc/!dc and +mc/!mc
- tests: add DeleteContainer to permission mocks where dirs are deleted

Directory Delete/Move now requires explicit DeleteContainer/MoveContainer
permission. This is a breaking change — existing roles have been updated.
@flash7777
Copy link
Copy Markdown
Author

Thanks for the approval @glpatcern! Is there anything else needed before this can be merged? Happy to address any remaining concerns.

@flash7777
Copy link
Copy Markdown
Author

Note: after your approval on May 28, we pushed two additional commits on May 30:

  1. docs: clarified immutable semantics (file=freeze vs container=protect, self vs parent rule) — documentation only
  2. feat: added set_immutable_file (field 23) and set_immutable_container (field 24) to ResourcePermissions — separates the permission to freeze files (irreversible) from the permission to protect containers (reversible)

Would appreciate a quick look at these additions before merge. The rest is unchanged from what you approved.

flash7777 pushed a commit to flash7777/reva that referenced this pull request May 30, 2026
The code references fields from cs3org/cs3apis#272 (DeleteContainer,
MoveContainer, SetImmutableFile, SetImmutableContainer, Immutable).
These will compile once go-cs3apis is regenerated after cs3apis merge.
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