Version history

Every approved write to a share's content is captured as an immutable row in the version history. The history covers content edited via:

  • anchorify <file> updates (CLI).
  • POST / updates (API).
  • Edits from the dashboard's in-browser editor.
  • Restores (rolling back to an older version appends a new rollback row — the restore itself is versioned).
  • Approved suggestions (see Suggestions).
  • Agent-edit calls (/api/v1/agent-edit).

Every version stores the full content as it was at write time. Restoring an older version copies its content into the live share; the previous live content remains in history.

Accessing the history

Web

From the dashboard, open a share's actions menu () → Version history. The page lists every approved version newest-first, with author, timestamp, source (publish / rollback / suggestion / agent_edit), and byte count. Click any row to:

  • View the version's full body (read-only).
  • Diff against the current version — a line-by-line comparison.
  • Restore — make the older version the live content.

API

The full surface lives under /api/v1/shares/:id/versions/*:

All four require cookie-session auth as an admin of the share's owner org. Per-user CLI tokens don't yet expose the version surface (this is a follow-up).

Diff format

The diff endpoint returns a flat list of line-keyed entries:

{
  "from": {"id": "...", "created_at": 1717400000000},
  "to":   {"id": "...", "created_at": 1717449600000},
  "lines": [
    {"kind": "equal",  "text": "# Q1 report"},
    {"kind": "remove", "text": "Looks great."},
    {"kind": "add",    "text": "Looks great. Updated 5/15."}
  ]
}

Lines are computed with a longest-common-subsequence diff. For very large or binary content, the diff falls back to {"truncated": true, "lines": []} with a reason field — the dashboard surface shows a "view both versions side by side" link in that case instead of attempting to render the diff.

Restore semantics

Restoring version V_old does NOT delete any newer versions. The flow is:

  1. The current shares.content is copied into V_old.content (this is a no-op since V_old is what we're restoring to).
  2. A new version row is appended to history with source='rollback' and the same content as V_old. The rollback itself is versioned.
  3. shares.content (and filename, content_type) flip to V_old's values.
  4. A share.restore audit event lands on the owner org's audit feed.

The previously-live version stays in history — you can restore back to it just like any other.

Version status

Each version has a status of approved, suggested, or rejected:

  • approved — the version is or once was the live content. Includes all publish/update/rollback/agent_edit sources, plus suggestions that were approved.
  • suggested — an open proposed change. Not reflected in shares.content until an admin approves.
  • rejected — a proposed change that was turned down. Kept in history for audit.

The dashboard list collapses rejected rows by default; pass ?status=approved to the list endpoint to hide suggestions entirely.

What's not in here

  • Branching / multiple parallel versions — there's one linear history per share.
  • Per-line annotations — comments attach to the whole share, not to a diff line.
  • History deletion — there's no way to scrub an old version from history. If a version contains material that must be deleted, contact the operator.