Together
Workspaces, repositories, and sharing
Working together needs more than an invite button. It needs a boundary where rules actually bind, a shelf that holds exactly what you chose, and a way to hand one person one thing — no more, and not forever unless you mean it. Scellis builds each of these as a separate instrument, and it enforces the ones that matter on the server, beneath anything a client bug could reach.
Five grouping concepts carry all of this. Each owns exactly one axis, and they are never conflated:
| Concept | Its one axis |
|---|---|
| Pack | Ships content |
| Listing | Sells it |
| Workspace | Governs a team |
| Repository | Curates a shelf |
| Pool | Computes together |
A Pack ships, a Listing sells, a Pool computes — each has its own page. This one is about the middle of the table: how a team governs, how a collection stays curated, and how work moves between people.
A Workspace governs#
A Workspace is the team boundary. Membership is the isolation boundary: what lives inside a Workspace is visible to its members and to nobody else. Four roles order what a member may do — owner > admin > editor > viewer — strictly ordered.
Enforcement is server-side, and it is layered. The interface reflects your role; it never implements it. Beneath the application sits a second, independent floor: row-level security policies at the database itself decide which rows a request can see. That floor is generated, not handwritten — one generator covers both visibility lattices, grants, and link-grants — so a client bug cannot widen access, because the client was never the thing deciding.
Note
Hiding a button is courtesy. The server-side check is the boundary, and the database's row-level security is the floor beneath it — neither cares what the interface claims.
Policy the interface cannot override#
A Workspace also carries policy, and policy is an enforcement boundary, not a preference. A Workspace can require that only signed Packs install, forbid network effects outright, enforce deterministic-only execution, and make its logs immutable. No local setting overrides any of it: policy binds on the server, for every member, whatever their client does.
Audit logs make the boundary demonstrable. Admins can query and export who ran what, and when. For regulated work, that is the point of the whole arrangement — not a policy you assert, but a boundary you can show an auditor.
Entitlements can belong to the Workspace#
Governing a team and paying for one are the same axis, so Scellis keeps them on one model. An entitlement — a tier plan or a purchased pack — can be granted to an identity or to a Workspace, seat-pooled across its members. Team, course, and campus licensing is therefore data, not a retrofitted second billing system: buy once for the Workspace and every member is covered, and the same server checkpoint that enforces roles enforces the plan. How the commercial side of that works — settlement, invoices, refunds — is the subject of the marketplace, and the tiers themselves live on the pricing page.
A Repository curates#
A Repository is a named, shareable collection of anything — workflows, models, datasets, blocks — with every entry pinned to a version. It is one shelf, holding exactly what you curated. And because the versions are pinned, the shelf is stable: someone publishing version 12 of a model does not silently change the version 7 you chose to stand behind. Immutable versions coexisting is what makes a Repository citable as a whole — a reading list that resolves the same way tomorrow.
A Repository has no roles and no policies, deliberately. If you find yourself wanting roles on a Repository, what you want is a Workspace: a Repository curates, a Workspace governs. One axis each — which is also why a Repository is not a Pack. A Pack ships a closed dependency graph as one signed unit; a Repository just points at versions you assembled.
Visibility moves one way; sharing is a Grant#
Every entity has a visibility, and visibility is monotonic: private → workspace → public, promotion only. Demotion exists, but as a different act with a different name — an unpublish is distinct and audited, never a quiet slide backwards. And nothing goes public without an SPDX license attached.
Sharing with a person is deliberately not a visibility value. It is a Grant: a per-person capability, ordered viewer ⊏ commenter ⊏ editor ⊏ owner, with an optional expiry and instant revocation. “Shared with me” is not a second storage system; it is a query over your grants — the same grant that gives an editor run control in a live session. Invitations have the same shape: you invite by email, and accepting mints a Grant.
Finding people to share with does not expose them. People discovery returns only opt-in public profile fields — handle, display name, avatar — never an email address, and never an inventory of who owns what. A profile can also stay out of discovery entirely.
Two kinds of share link#
A link can mean two different things, so Scellis has two different links and never blurs them. A snapshot link resolves to a frozen, content-addressed version: immutable, login-free, self-verifying — what arrives can prove it is what the link names. This is the reproducible-by-URL primitive; a colleague opens exactly the committed version you shared, not whatever your draft became overnight.
A session link opens the live, editable draft — and therefore requires identity. Even a visitor without an account co-edits under a stable, attributable anonymous handle, so everything in a live session has an author. A live draft is never hashed; when you need something citable, commit it and send the snapshot link instead.
In both cases, the link secret lives only in the URL fragment — the part after “#”, which the browser never sends to the server. The server stores only a hash of the secret: it can recognize a link it issued without being able to reconstruct it.
Honest limits
Revocation is forward-effective. Revoking a grant or a link cuts off future access instantly, but bytes a collaborator already synced to their device cannot be recalled — no system can un-send data, and Scellis does not pretend to. And for regulated documents, policy can forbid bearer links entirely: identity-bound viewing only.
Propose the change back#
Reading is the entry point to improving. Any entity you can read, you can fork; once your fork is better, you propose the change back. The owner reviews a real diff — the change itself, not a description of it — and merges via a 3-way merge. An accepted change lands as an ordinary new version, indistinguishable in kind from one the owner wrote. A proposals inbox on the Home surface keeps review visible, so a good change never depends on someone remembering to look.
Ownership itself moves through the same loop: transferring an entity is a propose-and-accept, exactly like any other change. It is the same fork-and-propose motion that makes the sharing graph a two-way street rather than a set of dead-end copies.