PAZATOR DOCS
SYNC
INFRASTRUCTURE — v0.Jul326

PZLS
Server.

PZLS is the sync server. LSAD (Local Sync Admin Dashboard) is its built-in admin panel, wrapped as an Electron desktop app. Sarparast is the main Pazator app that connects to PZLS.

Quick Start

1

Install dependencies.

cd PZLS
npm install
npx electron-rebuild  # rebuild native SQLite for Electron
2

Start the server.

npm start

Runs on http://localhost:3456. Set PORT to change it:

PORT=8080 npm start
3

Launch the desktop app (LSAD).

npm run desktop

Opens the admin panel in a native Electron window. Or just open http://localhost:3456 in a browser.

4

In Sarparast, click System → PZLS → enter the server URL → Test Connection. Register an account (first user is admin).

5

Push your data via System → Push. Pull to download server data.

Account System

Bearer token auth. Rate-limited on login/register (10 attempts/min by default). Disabled accounts can't log in. Users can set an email and display name on registration or later via profile update.

POST /api/auth/registerCreate account — {username, password, email?, displayName?}
POST /api/auth/loginLogin — {username, password}{token, user}
POST /api/auth/logoutInvalidate session
GET /api/auth/meCurrent user info (email, displayName included)
POST /api/auth/change-passwordChange password — {currentPassword, newPassword}
POST /api/auth/update-profileUpdate email/displayName — {email?, displayName?}
GET /api/auth/sessionsList your active sessions
DELETE /api/auth/sessions/:tokenKill one of your sessions

Passwords: scrypt + random salt. Sessions expire after 24h (configurable via TOKEN_TTL_MS).

Data Sync

All entities live in a shared SQLite database. Stores: humans, others, tags, cases, chats, relationships.

Full Sync

GET /api/syncPull all data
POST /api/syncPush data — {clientVersion, stores}
GET /api/sync/ops?since=N&limit=500Operation log (paginated)
POST /api/sync/opsPush operations individually with conflict detection
GET /api/sync/changes?since=NChanges since version
GET /api/sync/statusServer health + account stats
GET /api/sync/storesRecord counts per store

Incremental Sync (cursor-based)

For large datasets, use cursor-based pagination instead of full pulls. Each response includes a nextCursor token (base64-encoded composite cursor over (store, id)).

GET /api/sync/cursor?cursor=&limit=500&store=Paginated entity pull — returns {entities, nextCursor, hasMore, latestSeq}

Conflict Detection

When pushing via POST /api/sync/ops, each operation carries an expectedVersion. If the server's version differs, it returns {conflict: true, serverVersion, serverData} instead of overwriting. The client can then merge or prompt the user.

Conflict resolver UI is available in Pazator via System → Resolve Conflicts — view server vs client versions, dismiss individual conflicts, or use AI auto-solve to merge them intelligently.

Push format

{
  "clientVersion": 0,
  "stores": {
    "humans": { "id1": { "name": "..." } },
    "others": {},
    "tags": {},
    "cases": {},
    "chats": {},
    "relationships": {}
  }
}

E2E Encryption

Pazator supports client-side E2E encryption. When enabled in Settings → Security → E2E Encryption, all data is encrypted with AES-256-GCM before leaving the browser. The server stores it encrypted and decrypts on pull. The encryption key is derived from a user-chosen passphrase and stored locally.

POST /api/sync/encryption-keyRegister an encryption key (scrypt-derived from passphrase)
GET /api/sync/encryption-statusCheck if encryption key is set for your account

Server-side encryption (AES-256-GCM) also applies automatically to classified entities (confidential+) using the server's encryption.key file.

Search

GET /api/search?q=&store=&page=&perPage=Server-side search via SQL LIKE across all entity data

File Storage

Upload files (images, documents) linked to entities. 10MB max per file.

POST /api/files/uploadUpload file (base64) — {name, mimeType, data, entityId, entityStore}
GET /api/files/:idDownload raw file
GET /api/files/meta/:idFile metadata (no binary)
GET /api/files?entityId=&entityStore=List files for an entity
DELETE /api/files/:idDelete a file (owner or admin)

Other Endpoints

GET /api/resolve?threshold=0.6Jaro-Winkler entity resolution
POST /api/queryExecute SQL against external DB — {connectionString, query}

Admin Endpoints (admin role required)

GET /api/admin/configServer config: node version, paths, env vars
GET /api/admin/exportFull DB dump (JSON)
POST /api/admin/importRestore from dump
GET /api/admin/usersList all users
PATCH /api/admin/users/:idUpdate user — {disabled, role, email, displayName}
POST /api/admin/users/:id/reset-passwordAdmin password reset — terminates all sessions
DELETE /api/admin/users/:idDelete user and their data
GET /api/admin/users/:id/sessionsList a user's sessions
DELETE /api/admin/sessions/:tokenForce-kill any session
GET /api/admin/ops?since=N&limit=200Audit log (paginated)
GET /api/admin/adminsList forced admin usernames
POST /api/admin/adminsSet forced admin list

LSAD — Admin Panel

The built-in admin panel (LSAD) is served at / on the PZLS server. It includes:

  • Dashboard — stats grid, store breakdown bar chart, recent operations feed (live via WebSocket), connected clients
  • Users — user list with email, display name, status, last active, enable/disable, password reset, role change, forced admins config
  • Data — browse all entities with live search, click to view JSON
  • Changelog — paginated operation log with colored action pills
  • Sessions — view and kill your own login sessions
  • Config — runtime info, paths, environment variables
  • API Test — test any endpoint

Launch via npm run desktop (Electron) or open http://localhost:3456 in a browser.

Architecture

SQLite via better-sqlite3. Single shared entities table. Encryption-at-rest for classified entities (AES-256-GCM). Op log for audit trail.

PZLS/
  server.js              # Express server + WebSocket
  db.js                  # SQLite schema + queries
  electron.js            # Electron main process
  package.json
  data/
    pazator.db           # SQLite database
    encryption.key       # Auto-generated AES key

From Sarparast

The logo menu shows connection status:

  • Green — logged in and connected
  • Orange — connected but not logged in
  • Grey — not configured

System → PZLS to configure. Available actions:

  • Push — upload local data to server (queued if offline)
  • Pull — download all server data
  • Incremental Pull — cursor-based paginated download (avoids timeouts on large datasets)
  • Flush Queue — retry any queued offline operations
  • Resolve Conflicts — view and resolve merge conflicts, with AI auto-solve

Admin users see System → Admin Panel for audit log, user management, stores breakdown, server config, sessions, and export/import.


Naming

PZLS = the sync server itself (Node.js + Express + SQLite + WebSocket).
LSAD = the admin panel UI (Electron app and/or browser).
Sarparast = the main Pazator app (50K-line SPA).