Skip to content

Share and Version Pipelines Across a Team#

This guide shows how to fork, diff, share, and import pipelines through the web API — the collaboration primitives for working across users and teams.

Overview#

Operation Description Endpoint
Fork Copy a pipeline to your workspace POST /api/pipelines/{id}/fork
Diff Compare two pipelines POST /api/pipelines/diff
Share Create a shareable link POST /api/pipelines/{id}/share
Import Import from share link POST /api/pipelines/import

Fork#

Create an independent copy of a pipeline in your workspace. The fork is a full copy — changes to the original do not affect the fork, and vice versa.

# API — ownership comes from your session, so no user id is sent
curl -X POST http://localhost:8080/api/pipelines/pipeline-abc/fork

# Response
{
  "forked_id": "pipeline-def",
  "name": "my-analysis (fork)"
}

Forks record their lineage — the forked_from field tracks the source pipeline.

Diff#

Compare two pipelines and see what changed:

curl -X POST http://localhost:8080/api/pipelines/diff \
  -H "Content-Type: application/json" \
  -d '{"toml_a": "<workflow-a TOML>", "toml_b": "<workflow-b TOML>"}'

# Response
{
  "diffs": [
    {
      "path": "rules",
      "category": "rules",
      "description": "rule \"align\": shell command changed",
      "severity": "info"
    }
  ]
}

Share#

Create a shareable link for a pipeline:

curl -X POST http://localhost:8080/api/pipelines/pipeline-abc/share \
  -H "Content-Type: application/json" \
  -d '{"visibility": "link", "expires_in_days": 30}'

# Response
{
  "share_url": "oxo+https://lab.example.com:8080/share/abc123",
  "access_token": "abc123",
  "expires_at": "2024-02-12T00:00:00+00:00"
}

Visibility levels (link / public — public is an alias of link) are stored on the share record; other values (e.g. workspace) are rejected with UNSUPPORTED_VISIBILITY. The share URL opens a public read-only landing page (see Share Landing Pages below); programmatic consumption goes through the import API below.

Import#

Import a pipeline from an oxo+https:// share link (oxo+http:// is accepted too — the token, not the scheme, is what the import validates):

curl -X POST http://localhost:8080/api/pipelines/import \
  -H "Content-Type: application/json" \
  -d '{"url": "oxo+https://lab.example.com:8080/share/abc123"}'

# Response
{
  "pipeline_id": "pipeline-xyz"
}

The oxo+https:// protocol prefix makes share links explicit and unambiguous — you can paste them into any tool and the intent is clear.

Import behavior:

  • Creates a full copy of the shared pipeline
  • Records the source via forked_from
  • Sets visibility to private by default
  • Checks share expiration before allowing import

Permissions Model#

A simple three-state visibility model:

Level Access
Private Only the owner can view/edit (the default for imported pipelines)
Shared (link / workspace) Read-only access via share/import
Admin Can view all, manage users

No nested RBAC. No group hierarchies. Simple and transparent.

Share Landing Pages#

A share link (oxo+https://host:port/share/<token>) opens a public read-only landing page — pipeline name/version, DAG shape, the full TOML, the owner, expiry, and the most recent terminal run as provenance. No session is required to view it (the token is the authorization). The Import into my workspace action copies the pipeline to the acting user's account (login required — the API enforces it).

Visibility is now enforced server-side: private pipelines are owner/admin-only, workspace pipelines are readable (not writable) by every authenticated user, link pipelines are reachable only through their share token.

Version History#

Every save/update snapshots the previous pipeline content (up to 50 revisions). In the editor's History tab you can load any snapshot into the editor or roll back — rollback preserves the current version as a new revision, so nothing is ever lost.

Audit Trail#

Every state-changing API call (fork, share, import, run, …) is recorded by the audit middleware — any non-GET request lands in audit_logs with the acting user, method+path, and result. View audit logs via GET /api/audit?days=7.