Sharing

Per-process access, separate from app-scoped permissions. Lets a run be opened to people who could not otherwise see it.

UI: ProcessSharingPanel.tsx in the process runner. API: /api/process/{id}/sharing.


What it does

App grants answer "may this person use processes at all." Sharing answers "may this person see this run." A user with only processes:read sees their own runs; sharing is how a specific run reaches someone else without granting them processes:read_all.


Two independent mechanisms

What a declared app member with the URL can do.

ValueEffect
noneDefault. Link alone grants nothing.
viewerAn authenticated app member with the link may read.
contributorAn authenticated app member with the link may read and act, subject to step/field gates.

Neither link visibility nor an assignment bypasses the required application membership boundary. Anonymous/nonmember access is denied by the deployment host even if middleware admits an optional-auth request to the handler. This is an intentional cutover access difference, not automatic preservation of old public links. See application access.

Assignments — named people

Field
userIdAuth0 sub
roleviewer or editor
displayName, emailCaptured at assignment time for display

Members come from /api/org/members, which resolves declared collaborators across affiliations.


The vocabulary problem

Three role words are in play and two are near-synonyms:

defaultVisibility:  none  │  viewer  │  contributor
assignment role:           │  viewer  │  editor

contributor (link) and editor (assignment) both mean "may act," but the words differ by mechanism. viewer means the same thing in both. They are separate types — ProcessSharingDefaultVisibility and ProcessSharingRole — not one shared enum.


Defaults

Every process starts closed:

sharing: { defaultVisibility: "none", assignments: [] }

Set in startProcess. Nothing is shared unless someone shares it.


Where it meets the spine

Sharing is checked in lib/require-process-read.ts and lib/require-process-write.ts, which resolve access from four sources:

  1. Owner (triggeredBy)
  2. Admin (processes:read_all)
  3. An assignment naming this user
  4. defaultVisibility — inside verified app membership

Sharing widens access. It never narrows it: an admin with processes:read_all sees every run in that app regardless of its sharing settings.


Legacy values

ProcessSharingVisibility ("private" | "public") is deprecated. Old documents are migrated on read in getProcessSharing. Do not write these values.


Known gaps

Contributor links widen access for authenticated principals; they do not permit anonymous writes. Sharing is process-specific, not organization-level isolation. There is no general expiry or retention policy attached to a link; revocation changes the sharing configuration. Treat public links and assignment changes as explicit access decisions, and test direct requests as well as UI.