verstak-docs/docs/compose/specs/2026-06-20-sync-server-and-...

8.4 KiB

Sync Server & Plugin Design

[S1] Problem

Verstak2 needs synchronization between devices. The old Verstak (~/git/verstak) has a working sync server and client, but Verstak2 is a platform architecture with plugins. Sync must be implemented as:

  1. A separate sync server repository
  2. A sync plugin that provides settings UI via the plugin manager

[S2] Sync Server

Location

Separate repository: verstak-sync-server

Source

Based on ~/git/verstak/cmd/verstak-server/ with minimal changes.

Structure

verstak-sync-server/
  cmd/server/main.go
  internal/
    server/
      server.go
      routes.go
      handlers_api.go
      handlers_auth.go
      handlers_admin.go
      middleware.go
      config.go
      schema.go
      tokens.go
      smtp.go
  go.mod
  go.sum
  README.md

API Endpoints

  • POST /api/v1/sync/push — push operations
  • POST /api/v1/sync/pull — pull operations
  • POST /api/v1/blobs/ — upload blob (multipart)
  • GET /api/v1/blobs/:sha256 — download blob
  • POST /api/client/pair — device pairing with login/password
  • POST /api/auth/test — test credentials
  • GET /api/client/me — device info
  • POST /api/client/revoke-current — revoke current device
  • POST /api/client/revoke-device — revoke specific device (web)
  • GET /api/v1/health — health check
  • Admin endpoints: /admin/dashboard, /admin/users, /admin/api/stats

Config

YAML file at data/config.yml:

port: 47732
admin:
  - username: admin
    password_hash: "$2a$10$..."

Database

SQLite at data/server.db with tables:

  • server_users — user accounts
  • server_devices — paired devices
  • server_ops — sync operations
  • server_tombstones — deleted entities
  • server_idempotency_keys — idempotent push
  • server_user_devices — user-device mapping
  • server_audit_log — audit trail

[S3] Sync Plugin

Location

verstak-official-plugins/plugins/sync/

Manifest

{
  "schemaVersion": 1,
  "id": "verstak.sync",
  "name": "Sync",
  "version": "0.1.0",
  "apiVersion": "0.1.0",
  "description": "Vault synchronization across devices via Verstak Sync Server.",
  "source": "official",
  "icon": "sync",
  "provides": ["verstak/sync/v1", "verstak/sync.status/v1"],
  "requires": ["verstak/core/files/v1"],
  "permissions": [
    "files.read",
    "files.write",
    "network.remote",
    "settings.read",
    "settings.write",
    "ui.register"
  ],
  "frontend": {
    "entry": "frontend/dist/index.js"
  },
  "contributes": {
    "settingsPanels": [{
      "id": "verstak.sync.settings",
      "title": "Sync",
      "component": "SyncSettings"
    }],
    "statusBarItems": [{
      "id": "verstak.sync.status",
      "label": "Sync",
      "position": "right"
    }]
  }
}

Capabilities Provided

  • verstak/sync/v1 — sync provider capability
  • verstak/sync.status/v1 — sync status provider

Settings (Extended)

The plugin stores settings via settings.read/write API:

Key Type Default Description
serverUrl string "" Sync server URL
username string "" User login
password string "" User password (stored temporarily, not persisted)
syncInterval number 0 Auto-sync interval in minutes (0 = disabled)
autoSync boolean false Enable auto-sync
deviceName string hostname Device identifier
deviceId string "" Assigned device ID
deviceToken string "" Device auth token
lastStatus string "disabled" Connection status
lastSyncAt string "" Last successful sync timestamp
lastError string "" Last error message

Settings UI Component

SyncSettings.svelte — registered as settings panel via contributes.

Two states:

  1. Not configured — setup form:

    • Server URL input
    • Username input
    • Password input
    • "Test Connection" button
    • "Connect" button
  2. Configured — status view:

    • Status indicator (connected/disconnected/error/revoked)
    • Server URL display
    • Device Name display
    • Device ID display
    • Last Sync Time display
    • Last Error display (if any)
    • "Sync Now" button
    • "Disconnect" button
    • "Reset Key" button
    • Sync Interval input + Save button
    • Auto-sync toggle

Backend Integration

The plugin uses VerstakPluginAPI to:

  • Read/write settings via settings.read/write
  • Call backend methods for sync operations

Backend methods needed in verstak-desktop:

  • SyncStatus() — get current sync status
  • SyncConfigure(serverURL, username, password) — pair device
  • SyncDisconnect() — disconnect and revoke
  • SyncTestConnection(serverURL, username, password) — test credentials
  • SyncSetInterval(minutes) — set auto-sync interval
  • SyncNow() — trigger immediate sync
  • ResetSyncKey() — clear device token

Status Bar Item

Shows sync status in the bottom-right status bar:

  • Icon: sync icon
  • Label: status text (Connected/Disconnected/Error)
  • Click: opens plugin settings

[S4] Data Flow

┌─────────────────────────────────────────────────────────┐
│                    Verstak Desktop                       │
│  ┌──────────────┐    ┌──────────────┐    ┌───────────┐ │
│  │ Plugin Manager│───▶│ Sync Plugin  │───▶│ Settings  │ │
│  │   (Settings)  │    │  (UI Panel)  │    │   API     │ │
│  └──────────────┘    └──────┬───────┘    └───────────┘ │
│                             │                            │
│  ┌──────────────────────────▼──────────────────────────┐│
│  │              VerstakPluginAPI                        ││
│  │  settings.read/write → files.read/write              ││
│  └──────────────────────────┬──────────────────────────┘│
│                             │                            │
│  ┌──────────────────────────▼──────────────────────────┐│
│  │           Core Platform (Go Backend)                 ││
│  │  SyncService: RecordOp, GetUnpushedOps, MarkPushed  ││
│  │  SyncClient: Push, Pull, UploadBlob, DownloadBlob   ││
│  └──────────────────────────┬──────────────────────────┘│
└─────────────────────────────┼───────────────────────────┘
                              │ HTTP
                              ▼
┌─────────────────────────────────────────────────────────┐
│                  Verstak Sync Server                     │
│  SQLite: users, devices, ops, tombstones                │
│  Blobs: SHA-256 content-addressed storage               │
│  API: push/pull, pair, auth, admin                      │
└─────────────────────────────────────────────────────────┘

[S5] Implementation Order

  1. Sync Server — copy and adapt from ~/git/verstak/cmd/verstak-server/
  2. Backend API — add sync methods to verstak-desktop/internal/api/app.go
  3. Sync Plugin — create plugin structure with manifest and frontend
  4. Settings UI — implement SyncSettings.svelte component
  5. Status Bar — add sync status indicator
  6. Testing — E2E tests for settings UI, integration tests for sync

[S6] Testing Strategy

  • Unit tests: Sync client (push/pull), settings read/write
  • E2E tests: Settings UI (configure, disconnect, sync now)
  • Integration tests: Full sync cycle (two devices, push/pull)
  • Manual verification: Real sync server with two vault instances