Skip to content

Usage

This section covers day-to-day interaction patterns for users who need to read, write, pin, and synchronize state. It focuses on the currently deployed general interface shape.

The general compose network exposes three primary web clients and one filesystem-oriented service: Explorer (/explorer/), Workbench (/workbench/), Gateway (/docs plus /api/v1/...), and File System (WebDAV at /webdav/). Together they cover the full operator/developer loop: inspect data, make changes, verify outcomes, mount journal state into ordinary file tools, and convert successful workflows into repeatable API calls.

The Explorer is the state-navigation and content-management interface. It now has three explicit modes:

  • Ledger
    • the default landing mode
    • route-based browsing of committed state across bridges and snapshots
  • Stage
    • local editable staged state
    • file and directory oriented editing actions
  • Admin
    • visible only to interface admins
    • bridge registration and local bridge endpoint sharing
    • public window-size edits and interface admin-list management

Typical Explorer workflow:

  1. Start in Ledger and synchronize to the latest committed root.
  2. Use the route strip to browse from Self through bridges and historical snapshots.
  3. Select a ledger file to switch between content and proof views or pin/unpin it.
  4. Switch to Stage when you want to edit local staged files and directories.
  5. Use stage actions to create documents/directories, upload files, edit content, and download files.
  6. If you are an admin, use Admin to copy this node’s bridge endpoint, register peer bridges, tune the ledger window, or update the interface admin list.

The Explorer is best for operational tasks and data exploration because it separates committed ledger inspection from local staged editing while keeping both in one UI.

Explorer desktop view

The Workbench is the API-oriented query environment. Use it when you want precise control over requests, fast iteration on payload shape, and direct inspection of results.

Typical Workbench workflow:

  1. Start from a known request pattern (for example get, set!, pin!, or bridge!).
  2. Run the request in Scheme form and inspect the returned value.
  3. Iterate on arguments/authentication until behavior matches intent.
  4. Use the final request as a template for automation or service integration.

The Workbench is best for debugging and integration development because it exposes the request/response layer directly.

Workbench desktop view

The Gateway is the web-facing API surface for journal operations. Use it when clients should call stable, versioned HTTP routes instead of direct function-shaped interface requests.

Typical Gateway workflow:

  1. Start with GET /docs to review request and response schemas.
  2. Use GET /api/v1/general/size or another stable route to validate connectivity.
  3. Execute public general operations through GET routes (for example size, info, and trace).
  4. Execute restricted general and optional root operations through authenticated POST routes.
  5. Move validated requests into application clients or automation scripts using the same gateway contracts.

The Gateway is best for service integration because it standardizes journal calls into HTTP endpoints with explicit request validation.

Gateway desktop view

The File System service projects journal state through WebDAV. Use it when existing tools should interact with Synchronic Web data through ordinary file and directory operations instead of direct API calls.

Typical File System workflow:

  1. Mount the share and work in /stage for ordinary mutable file operations.
  2. Browse /ledger/state for current committed content.
  3. Browse /ledger/<index>/state for a specific prior committed snapshot.
  4. Traverse /ledger/bridge/<name>/state for a bridged peer’s current committed state.
  5. Use /control/pin for explicit pin and unpin directives on discovered ledger paths.

The File System service is best for shell tools, editors, archives, source trees, and other workflows that already expect a hierarchical filesystem.

Filesystem projection overview:

/
├── stage/
│ └── ...
├── ledger/
│ ├── state/ (defaults to current head)
│ │ └── ...
│ ├── <index>/ (explicit historical snapshot)
│ │ ├── state/
│ │ │ └── ...
│ │ └── bridge/
│ │ └── <name>/
│ │ ├── state/
│ │ └── ...
│ └── bridge/
│ └── <name>/ (defaults to current head)
│ ├── state/
│ │ └── ...
│ └── bridge/
│ └── ...
└── control/
└── pin

Key semantics:

  • /stage is mutable.
  • /ledger/... is readable but content-immutable.
  • omitting an explicit <index> anywhere in a ledger path defaults to the current head (-1).
  • once you enter any state/ subtree, remaining path segments are ordinary file and directory names.
  • /control/pin is a synthetic UTF-8 file for pin and unpin directives against discovered /ledger/... paths.

Programmatic access is typically where teams standardize integrations across multiple services. The sections below focus on stable request patterns that are easy to lint, test, and automate.

Use this catalog as a quick orientation map. The /interface execution endpoint accepts Scheme or JSON runtime calls via content negotiation, while the conversion endpoints are for debugging and payload authoring.

EndpointDescription
POST /interfaceExecutes Scheme requests or JSON requests depending on Content-Type.
POST /interface/scheme-to-jsonConverts Scheme expressions into JSON payload representations.
POST /interface/json-to-schemeConverts JSON payloads back into Scheme forms for debugging and validation.

Public ledger/interface paths use flat token lists. In Scheme, write paths as lists such as (*state* alice notes) or (-1 *state* alice notes). In JSON, use the equivalent flat arrays, for example ["*state*", "alice", "notes"] or [-1, "*state*", "alice", "notes"].

When an indexed/committed operation needs a history index and no explicit index is present, the current head (-1) is used. Nested list paths are an internal ledger representation and are not accepted as public API input.

Restricted operations require an authentication field that identifies the caller and carries the interface secret.

Two caller identities are recognized:

  • Named user (e.g. alice): a registered user. The gateway injects this automatically when you are logged in via Kratos. When calling the interface directly, you supply it yourself with your username and the interface secret.
  • Root journal caller: omit identity in the authentication block. This is used by journal automation and has no path restrictions.

When calling through the gateway (/api/v1/...), you do not construct the authentication block — the gateway handles it from your session or API token. When calling the interface directly (/interface), you supply it manually:

(authentication ((identity alice) (credentials "interface-secret")))

Each user’s writable space is (*state* <username> ...). A user may only write to paths whose first segment after *state* matches their own username:

(*state* alice notes) ← alice can write; bob cannot
(*state* bob notes) ← bob can write; alice cannot

Reads are more permissive — any authenticated user can read another user’s paths unless the path contains *private*:

(*state* alice notes) ← any authenticated user can read
(*state* alice *private* journal) ← only alice (or root/admin) can read
TierIdentityPrivileges
Rootomitted identityAll operations on all paths.
AdminNamed user in the admin listAll operations on all paths.
UserNamed user not in the admin listNamespace and visibility rules above apply.

Operations requiring admin or root: bridge!, *secret*, *admins-get*, *admins-set*, *window-set*. Regular users receive a permissions-error on these.

Most JSON integrations can standardize on this envelope and only vary function and arguments. That keeps client implementations simple and makes troubleshooting easier across services.

FieldTypeRequiredNotes
functionsymbol/stringYesAPI function name
argumentsobject / association listUsuallyKeyword-style fields for ledger calls
authenticationalist / objectRestricted calls((identity alice) (credentials "secret")) for named users, or ((credentials "secret")) for the root journal caller

Note:

In Scheme form, API queries are association lists. In JSON form, they are objects with equivalent fields.

These examples are intentionally minimal and map directly to frequently used workflows. You can copy them into Workbench first, then move them into automation once validated.

((function get)
(arguments ((path (*state* docs article hash))
(pinned? #t)
(proof? #t)))
(authentication ((identity alice) (credentials "password"))))

Info: When to use pinned? and proof?

Use pinned? when you want to know whether a historical path remains pinned, and use proof? when you need the proof payload itself.

((function set!)
(arguments ((path (*state* docs article hash))
(value "0xabc123")
(expression? #t)))
(authentication ((identity alice) (credentials "password"))))
((function pin!)
(arguments ((path (-1 *state* docs article hash))))
(authentication ((identity alice) (credentials "password"))))
((function bridge!)
(arguments ((name journal_b)
(info-local ((interface "http://journal-b.example.org/api/v1/journal/interface")
(policy ((publish push) (subscribe pull)))
(role #f)
(remote-name journal_a)))))
(authentication ((credentials "password"))))

The converter treats JSON and Scheme as structurally equivalent where possible.

This mapping is the key mental model for moving between web client payloads and Scheme-native request forms. Once this is clear, advanced payloads become much easier to reason about.

SchemeJSON
symbolstring
listarray
association list ((k v) ...)object { "k": v, ... }
object-shaped assoc listobject

Special type wrappers are only needed where plain JSON cannot preserve Lisp/runtime semantics. If a payload seems unexpectedly interpreted, check whether a special type marker is required.

JSON markerScheme value
{"*type/string*": "text"}string
{"*type/quoted*": ...}(quote ...)
{"*type/byte-vector*": "deadbeef"}byte-vector
{"*type/vector*": [...]}vector
{"*type/pair*": [a, b]}dotted pair (a . b)
{"*type/rational*": "1/3"}rational
{"*type/complex*": "1+2i"}complex

Use /interface/scheme-to-json to generate exact JSON for complex expressions, and use /interface/json-to-scheme when debugging client payloads or validating round-trip conversions. For web clients, prefer object-shaped API queries (function, arguments, authentication) because they remain easier to read and diff than raw array forms, and reserve array-shaped JSON for raw root command calls. Prefer *type/string* for literal strings in JSON payloads whenever you need to avoid ambiguity in type conversion.

A common workflow is: prototype in Scheme, convert to JSON, integrate in client code, then round-trip with json-to-scheme during debugging. Teams that include conversion checks in their release process generally catch payload-shape regressions earlier.