8.4 KiB
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:
- A separate sync server repository
- 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 operationsPOST /api/v1/sync/pull— pull operationsPOST /api/v1/blobs/— upload blob (multipart)GET /api/v1/blobs/:sha256— download blobPOST /api/client/pair— device pairing with login/passwordPOST /api/auth/test— test credentialsGET /api/client/me— device infoPOST /api/client/revoke-current— revoke current devicePOST /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 accountsserver_devices— paired devicesserver_ops— sync operationsserver_tombstones— deleted entitiesserver_idempotency_keys— idempotent pushserver_user_devices— user-device mappingserver_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 capabilityverstak/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:
-
Not configured — setup form:
- Server URL input
- Username input
- Password input
- "Test Connection" button
- "Connect" button
-
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 statusSyncConfigure(serverURL, username, password)— pair deviceSyncDisconnect()— disconnect and revokeSyncTestConnection(serverURL, username, password)— test credentialsSyncSetInterval(minutes)— set auto-sync intervalSyncNow()— trigger immediate syncResetSyncKey()— 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
- Sync Server — copy and adapt from
~/git/verstak/cmd/verstak-server/ - Backend API — add sync methods to
verstak-desktop/internal/api/app.go - Sync Plugin — create plugin structure with manifest and frontend
- Settings UI — implement
SyncSettings.sveltecomponent - Status Bar — add sync status indicator
- 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