Suture Hub

Suture Hub is a self-hosted collaboration server for Suture repositories. It provides a web UI, HTTP API, and gRPC access for push/pull, repository browsing, user management, and replication.

Starting a Hub

suture-hub --db hub.db
# Web UI at http://localhost:50051
# API at http://localhost:50051/api/v2

Flags:

FlagDefaultDescription --addr0.0.0.0:50051Bind address --dbin-memorySQLite database file path --replication-rolestandalonestandalone, leader, or follower

Omit --db for in-memory storage (useful for testing). Use --db hub.db for persistent storage.

Authentication

When a hub has no users or tokens, all operations are open. Once the first user is created, authentication is required.

Create a User (Admin Only)

curl -X POST http://localhost:50051/auth/register \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{"username": "alice", "display_name": "Alice", "role": "member"}'

Roles: admin (full access), member (push/pull), reader (pull only).

Generate an API Token

curl -X POST http://localhost:50051/auth/token \
  -H "Authorization: Bearer <admin-token>"

CLI Login

suture remote add origin http://localhost:50051
suture remote login

Ed25519 Key Authentication

Generate a keypair and register the public key with the hub. Pushes signed with the corresponding private key are verified automatically.

suture key generate

Pushing and Pulling

CLI

suture remote add origin http://localhost:50051
suture push
suture pull
suture clone http://localhost:50051/my-repo

API

Push:

curl -X POST http://localhost:50051/push \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "repo_id": "my-repo",
    "patches": [...],
    "branches": [...],
    "blobs": [...]
  }'

Pull:

curl -X POST http://localhost:50051/pull \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "repo_id": "my-repo",
    "known_branches": [...]
  }'

Protocol V2 (Delta Transfer)

Suture Hub supports delta-based transfer for efficient syncs when both sides share common blobs.

# Handshake to discover capabilities
curl -X POST http://localhost:50051/v2/handshake \
  -H "Content-Type: application/json" \
  -d '{"client_version": 2}'

Response includes server_capabilities with supports_delta and supports_compression flags.

Web UI

Open http://localhost:50051 in a browser. Features:

  • Repository list -- browse all repositories
  • File tree -- navigate files at any branch (/repos/{id}/tree/{branch})
  • Branch browser -- view branches and their targets
  • Patch history -- paginated commit log with cursor-based pagination
  • Branch protection -- prevent force-push on protected branches
  • Search -- search repositories and patches by keyword

Mirrors

Mirror a remote repository locally for redundancy or faster access.

Setup a Mirror

curl -X POST http://localhost:50051/mirror/setup \
  -H "Content-Type: application/json" \
  -d '{
    "repo_name": "local-copy",
    "upstream_url": "http://upstream-hub:50051",
    "upstream_repo": "upstream-repo"
  }'

Sync a Mirror

curl -X POST http://localhost:50051/mirror/sync \
  -H "Content-Type: application/json" \
  -d '{"mirror_id": 1}'

Check Mirror Status

curl http://localhost:50051/mirror/status

CLI Mirror

suture remote mirror http://upstream/repo upstream-name

Replication

Suture Hub supports leader-follower replication for high availability.

Leader (--replication-role leader):

  • Pushes replication log entries to followers every 30 seconds
  • Accepts peer management requests

Follower (--replication-role follower):

  • Accepts replication entries from the leader
  • Read-only for replication sync endpoint

Standalone (default):

  • No replication; works independently

Manage Peers (Leader Only)

# Add a follower
curl -X POST http://localhost:50051/replication/peers \
  -H "Content-Type: application/json" \
  -d '{"peer_url": "http://follower:50051", "role": "follower"}'

# List peers
curl http://localhost:50051/replication/peers

# Remove a peer
curl -X DELETE http://localhost:50051/replication/peers/1

# Check replication status
curl http://localhost:50051/replication/status

API Reference

Repositories

MethodEndpointDescription GET/reposList all repositories POST/reposCreate a repository GET/repo/{id}Repository info (patch count, branches) DELETE/repos/{id}Delete a repository

Branches

MethodEndpointDescription GET/repos/{id}/branchesList branches POST/repos/{id}/branchesCreate a branch DELETE/repos/{id}/branches/{name}Delete a branch POST/repos/{id}/protect/{branch}Protect a branch POST/repos/{id}/unprotect/{branch}Unprotect a branch

Content

MethodEndpointDescription GET/repos/{id}/tree/{branch}File tree at branch GET/repos/{id}/blobs/{hash}Get blob content (base64) GET/repos/{id}/patchesPaginated patch history

Sync

MethodEndpointDescription POST/pushPush patches (v1) POST/pullPull patches (v1) POST/push/compressedPush with Zstd compression POST/pull/compressedPull with Zstd compression POST/v2/pushPush with delta transfer (v2) POST/v2/pullPull with delta transfer (v2)

Auth

MethodEndpointDescription POST/auth/tokenGenerate API token POST/auth/verifyVerify a token POST/auth/loginLogin with username + token POST/auth/registerCreate a user (admin only)

Users

MethodEndpointDescription GET/usersList users (admin only) GET/users/{username}Get user info PATCH/users/{username}/roleUpdate user role (admin only) DELETE/users/{username}Delete user (admin only)

Mirrors

MethodEndpointDescription POST/mirror/setupRegister a mirror POST/mirror/syncSync a mirror GET/mirror/statusMirror status DELETE/mirrors/{id}Delete a mirror

Replication

MethodEndpointDescription POST/replication/peersAdd a replication peer (leader) GET/replication/peersList peers DELETE/replication/peers/{id}Remove a peer GET/replication/statusReplication status POST/replication/syncAccept replication entries (follower)

Other

MethodEndpointDescription GET/search?q=Search repos and patches GET/activityActivity log (paginated) POST/handshakeProtocol version handshake (v1) POST/v2/handshakeProtocol version handshake (v2)

gRPC Access

Suture Hub exposes a gRPC service alongside the HTTP API. See the crates/suture-hub/grpc/ directory for service definitions.

Rate Limits

Default limits (configurable):

OperationLimit Pushes100 per hour per IP Pulls1000 per hour per IP Token creation5 per minute per IP

Rate-limited responses include a Retry-After header.