Share resources
Workflows, plans, artifacts, and Git-backed evidence. Grant access inside your org.
A resource in Viewport is any object that can be shared or exported: a workflow definition, a plan, a workflow run, an artifact, a review packet, an inbox item, or a team Git Resource. Shareable resources go through the same ACL system. A polymorphic registry of grants where the subject is a user, a team, or a share group.
Context is intentionally different: it is team-owned memory or organization rules injected into runs. Do not model context as an arbitrary one-off shared object between people. Team membership, key grants, review policy, and the active team decide who can use or update team memory.
The model
Every shareable resource has a row in resources and zero-or-more rows in resource_acl_entries:
resources
id ulid
workspace_id ← the tenant
team_id ← present for team-scoped work
resource_type workflow | plan | vault | run | inbox | ...
resource_ulid pointer to the underlying record
owner_user_id who created it
visibility private | workspace | restricted
resource_acl_entries
resource_id → resources.id
subject_type user | team | share_group
subject_id → users.id | teams.id | share_groups.id
role owner | admin | reviewer | viewerSharing creates resource_acl_entries. Unsharing deletes them. There's no separate "permissions" surface. The ACL table is the answer.
Visibility modes
| Mode | Who sees it |
|---|---|
| Private | Only the owner + people explicitly granted via ACL entries. |
| Workspace | Everyone in the workspace can view (read-only). ACL entries can grant higher roles. |
| Restricted | Specific principals only. Like Private, but the UI signals there's a non-obvious access list. Audited every time someone reads. |
Team-scoped resources
Most execution resources are team-scoped:
- workflows and workflow routes;
- workflow runs and run artifacts;
- review packets and approval decisions;
- context packages, vaults, events, and candidate application receipts owned by the team;
- the primary Team Resource export target.
Sharing never crosses the organization boundary, and team-scoped resources cannot be attached to a team from another organization.
Share a workflow
- Open the workflow detail page.
- Click Share.
- In the modal, search for a user, team, or share group inside this org.
- Pick a role for them.
- Save.
Behind the scenes:
- A
resource_acl_entriesrow is created. - The recipient sees the workflow in their list immediately.
- An audit event
workflow.sharedis written with the actor, the subject, and the role.
Share a plan
Same modal. Same shape. Plans can be shared for review. The principal list is org-scoped. You can't share with a user outside the org.
For context, add the person to the owning team or update the team/organization context policy. That keeps memory aligned with the workflow and runner scope that will consume it.
Export to the team's Git Resource
When a team has a primary Git Resource, Viewport can produce a reviewable .viewport/ export:
.viewport/
team.json
workflows/definitions.json
workflows/routes.json
reviews/packets.json
artifacts/index.json
artifacts/workflow-run-artifacts.json
artifacts/comments.json
artifacts/bodies.json
context/packages.json
context/vaults.json
context/events.json
context/candidate-applications.jsonThese exports are receipts and portable contracts. They do not replace control-plane enforcement, but they make approvals, context decisions, and artifact provenance visible in Git.
Artifact comment and body exports are ciphertext-only. The control plane writes digests, key epochs, metadata, and provenance, but decrypted content stays on the trusted edge. When a reviewer unwraps an encrypted artifact body, Viewport records an audit event bound to the current body digest and key epoch before local decryption.
For remote Git resources, Viewport prepares a worker sync bundle instead of cloning or pushing from the API process. A runner or operator machine with repo access can fetch the bundle and apply it with:
vpd team-resource sync \
--server https://api.getviewport.com \
--workspace WORKSPACE_ID \
--executor EXECUTOR_ID \
--credential VP_EXECUTOR_TOKEN \
--resource TEAM_RESOURCE_ID \
--repo /path/to/team-resource-repo \
--push \
--jsonThe daemon verifies file hashes, rejects paths outside .viewport/, writes the
export, commits the result, optionally pushes to origin, and reports the
commit SHA back to Viewport. This keeps Git credentials on runner/operator
machines while preserving a
deterministic control-plane export.
Share groups (ad-hoc audiences)
Sometimes you want to share with "these 5 specific people" without making a team. That's a share group: a workspace-local list of principals that exists only to be the subject of an ACL entry.
Create one inline from the share modal: + New share group. Name it. Add people. Use it as a subject.
Share groups are also workspace-scoped. They cannot include users outside the org, and a share group from one org cannot grant access in another.
Unshare
Same modal. Remove the principal. The ACL entry is deleted; the resource is no longer visible to that principal (assuming they had no other grant path).
Unshares write an audit event.
What CAN'T be shared across orgs
Hard wall. The platform refuses with a 422 if you try to write an ACL entry where:
team.workspace_id != resource.workspace_idshare_group.workspace_id != resource.workspace_id- The subject user has no membership row in
resource.workspace_id
See Concepts: Trust and privacy for the invariants.
Resource roles
The role on an ACL entry maps to what the principal can do:
| Role | View | Comment | Edit | Approve | Share with others | Delete |
|---|---|---|---|---|---|---|
| viewer | ✓ | |||||
| reviewer | ✓ | ✓ | ✓ | |||
| editor | ✓ | ✓ | ✓ | ✓ | ||
| admin | ✓ | ✓ | ✓ | ✓ | ✓ | |
| owner | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
Each resource type has slight variations (a workflow's "approve" is "approve a plan generated by this workflow," etc.). Hover the role chips in the UI for resource-specific definitions.
Bulk share
To grant multiple principals at once, use the API:
POST /api/resources/{workspace}/workflows/{workflow_id}/share/bulk
Content-Type: application/json
{
"grants": [
{ "subject_type": "team", "subject_id": "t_platform", "role": "reviewer" },
{ "subject_type": "share_group", "subject_id": "sg_…", "role": "viewer" }
]
}See Reference: API.
Where to go next
- Approval policies. How shares affect inbox routing.
- Concepts: Inbox. The routing model.
- Audit log. What every share writes.