Context
Nested folder sharing is additive in v1:
- parent folder access continues to apply to child folders
- child folder shares can add users or grant higher rights
- if a user has access through multiple sharing scopes, the highest permission wins
- file shares remain additive and do not create boundaries
limited_access is reserved for a future feature
Before endpoints can safely allow nested folder shares, Cozy Stack needs shared backend helpers to compute effective access.
On the fly vs Copy Members
Option A: Copy inherited members into every child share
Pros:
- permission checks stay simple
- each child sharing doc contains a complete member list
- less resolver logic needed initially
Cons:
- parent membership changes require updating all nested child shares
- removing a user from a parent share risks stale copied access in children
- every inherited member must be replicated to every child share recipient
- move/merge behavior becomes harder to reason about
- child sharing docs become ambiguous: direct member, inherited member, copied member, or stale member
Option B: Access on the fly
Pros:
- parent sharing remains the source of truth
- no cascade updates when parent members change
- revocation is immediate when parent access is removed
- child sharing docs store only direct grants
- works better with future
limited_access
Cons:
- permission checks are more complex
- requires efficient CouchDB indexes
- needs request-level caching/batching to avoid repeated lookups
- archive/realtime/sync flows need extra care later
Decision
Use derived effective access.
Do not copy inherited parent members into child sharing docs during normal sharing updates.
Domain Model
Add/formalize access mode on io.cozy.sharings:
io.cozy.sharings
- access_mode: additive | limited_access
Rules:
- missing access_mode is treated as additive
- additive is the only enabled mode for this task
- limited_access is reserved for later
- io.cozy.files.referenced_by remains the marker for shared roots
- file-root shares are not restrictive boundaries
Internal service model:
type SharingScope struct {
SharingID string
RootID string
RootPath string
AccessMode string
ReadOnly bool
}
type EffectiveAccess struct {
CanRead bool
CanWrite bool
SourceSharingIDs []string
}
type AccessResolver struct {
inst *instance.Instance
fs vfs.VFS
}
func NewAccessResolver(inst *instance.Instance) *AccessResolver
func (r *AccessResolver) Resolve(targetID string) (*EffectiveAccess, error)
access, err := resolver.Resolve(target vfs.Fetche)
if err != nil {
return err
}
if !access.Can(permission.GET) {
return jsonapi.Forbidden(...)
}
// Internal/private helpers can exist, but not as public API:
func (r *AccessResolver) scopesFor(targetID string) ([]sharingScope, error)
func (r *AccessResolver) ancestorPaths(targetID string) ([]string, error)
func (r *AccessResolver) loadSharings(ids []string) ([]*Sharing, error)
Index
No index
We can have a Mango query instead of this index when we query all the files with the parent path using the same path index and then getinng sharing_ids from the reference_by list
req := &couchdb.FindRequest{
UseIndex: "dir-by-path",
Selector: mango.And(
mango.In("path", ancestorPathsAsInterfaces),
mango.Equal("type", consts.DirType),
mango.Exists(couchdb.SelectorReferencedBy),
),
Fields: []string{"_id", "path", "referenced_by"},
Limit: len(ancestorPaths),
}
Flow:
- Read target path from the already loaded file/folder.
- Build ancestor folder paths.
- Query shared-folder-roots-by-path once with ViewRequest.Keys.
- Bulk-load returned sharing docs.
- Keep active additive sharing scopes.
- Merge current user permissions.
Context
Nested folder sharing is additive in v1:
limited_accessis reserved for a future featureBefore endpoints can safely allow nested folder shares, Cozy Stack needs shared backend helpers to compute effective access.
On the fly vs Copy Members
Option A: Copy inherited members into every child share
Pros:
Cons:
Option B: Access on the fly
Pros:
limited_accessCons:
Decision
Use derived effective access.
Do not copy inherited parent members into child sharing docs during normal sharing updates.
Domain Model
Add/formalize access mode on io.cozy.sharings:
io.cozy.sharings
Rules:
Internal service model:
Index
No index
We can have a Mango query instead of this index when we query all the files with the parent path using the same path index and then getinng
sharing_ids from thereference_bylistFlow: