Item Sharing—Access Control List

Item sharing to users, projects, organizations and publicly at scale

Role-Based Access Control helps us model permissions for what a user can do in general: Can you create a document, see analytics, etc.However, that system can't tell you what a user can do with this specific item. For collaborative platforms, you need to design a system that supports this at scale. This is called building an Access Control List.

§The Primitive: Grants

A grant links an entity to an item. An entity is a user, project, organization, or the public. An item is any resource on your platform that can be shared. There are many ways to design this data model, but it's possible to have one table that answers all questions about all items.

With the table, we can easily express:

We can also easily support sharing an item with N users, M projects, and L organizations.

§Public Access as a grant, not a flag

Another common option is to have an is_public boolean on the item itself. It's my personal opinion that this is not the optimal choice, but rather having a __public__ sentinel entity to represent public access is better.

§Grant Resolution

When multiple grants exist that are applicable to the requesting user, there are a few viable options with trade-offs:

§Most specific wins

The closest relationship to the item takes precedence. A direct viewer grant won't be elevated by an org-wide editor grant. Most predictable, users can be intentionally restricted.It can surprise users who expect broader grants to elevate.

§Most permissive wins

If any grant gives you editor, you're editor. Simple to reason about, generous. You can never restrict access below what a broader grant allows.

§Most restrictive wins

Safe for compliance-heavy environments. Sharing becomes frustrating because restrictive org policies override direct shares.

At Gumloop, we choose most specific because it makes sharing behaviour most predictable. We built a resolver to centralize all this logic, and override it on a per-resource basis when needed.

§Cascading Grants

Items live inside other items. A file lives inside a folder. If someone shares the folder, should the files inside it be accessible? Without cascading, you'd need to duplicate grants for every child item whenever a parent is shared — a UX nightmare and a consistency bug waiting to happen. Because ACL is resolved per-item and RBAC acts as a ceiling, you can have child items inherit grants from their parent without worrying about the child bypassing org-level restrictions.

§Full delegation

A file inside a shared folder. The file has no grants of its own — it entirely inherits from the folder. If the folder is public, the file is public. If a user is shared on the folder as viewer, they're viewer on the file.

§Hybrid

A form linked to a spreadsheet. The form has its own general access grants — org-wide visibility, public link — but user-level shares cascade from the parent spreadsheet. If someone is shared as editor on the spreadsheet, they get at least editor on the form too. The form can also be independently shared with the org or made public.

§Standalone

Top-level items like folders and spreadsheets. Resolved purely from their own grants, no cascade. This is the base resolver shown above.

§The Right Question

When it comes to permissioning systems, my personal principal is: Make sure that the code asks the right question. With this system and the proper helpers to resolve permission, we can properly ask "What is this user's effective role on this specific agent, considering all grants that apply to them?"