Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Modellen Tools & Services
Oplossingen
Organisaties Ontwikkelaars Internet Service Providers Managed Service Providers AI-in-a-Box
Kenniscentrum
Ondersteuning Documentation Blog Downloads
Bedrijf
Over ons Onderzoek Vacatures Investeren Contact
Inloggen

SLWP wire protocol

SLWP (the ScaiLog Wire Protocol, version 0.1) is the small JSON-based protocol that carries log entries across the two hops of a ScaiLog deployment: from your service to the local agent, and from the agent to the central server. This page describes the local frame vocabulary, the batch codec used for the server hop, and the canonical checksum that protects a batch in transit.

Every SLWP message is a JSON object carrying a version field "v": "0.1". Unknown major versions are rejected; unknown fields are ignored, so the format can grow without breaking existing peers.

Local frames (SDK to agent)#

The SDK-to-agent hop is a local socket carrying newline-delimited JSON — one frame per line. The frame vocabulary is: emit, ack, nack, ping, pong (plus query, row, done for local reads).

The emit frame is the one that carries a log entry. It holds the routing and content of one entry in plaintext, with PI still in marker form:

json
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "v": "0.1",
  "op": "emit",
  "event_id": "01J...",
  "tenant": "acme",
  "service": "checkout",
  "env": "prod",
  "site": "SCAI-CHECKOUT-PAY-OK-001",
  "level": "info",
  "ts": "2026-07-13T10:00:00Z",
  "msg": "payment captured",
  "fields": {"amount": 4200},
  "pi": {"email": {"val": "jan@example.nl", "type": "direct_identifier"}},
  "subject": "usr_8842",
  "trace_id": null,
  "request_id": null
}

Note the shape of pi: a map from field name to {"val": <scalar or flat list>, "type": <pi_type>}. This is the pre-encryption shape — the agent runs the ingest pipeline on receipt, turning pi markers into encrypted pi_fields before anything touches disk.

The agent answers each emit with an ack (carrying the event_id) or a nack (carrying the event_id, an error code, and optional detail). ping/pong are the liveness check.

Batch codec (agent to server)#

The agent ships entries to the server's POST /v1/ingest in batches. A batch is NDJSON compressed with zstd: each entry is serialized to one compact JSON line, the lines are joined with newlines, and the whole body is zstd-compressed. Entries in a batch are in post-encryption shape — they carry pi_fields and pi_meta, not the plaintext pi markers.

Three headers accompany the body:

Header Meaning
X-SLWP-Version The SLWP version (0.1).
X-SLWP-Batch-Id The batch identifier.
X-SLWP-Checksum Checksum over the canonical body (see below).

NDJSON on the wire lets the server stream the body line by line rather than buffering a whole array.

Canonical checksum#

Each batch is integrity-checked with a SHA-256 checksum computed over a canonical form of the batch — not over the compressed bytes. The canonical form is JSON with sorted keys, ,/: separators, and no whitespace, taken over the object {"batch_id": <id>, "entries": [...]} before compression. The checksum is the string sha256:<hex>.

On receipt the server decompresses the body, recomputes the checksum over the same canonical form, and compares it to the X-SLWP-Checksum header. The check fails closed: a batch that arrives with no checksum header is treated as a mismatch (BATCH_CHECKSUM_MISMATCH) rather than waved through. Because the checksum is over canonical JSON, it is stable regardless of how any particular peer orders keys or spaces its output — which is what lets the four SDKs and the server all agree on it byte-for-byte.

Updated 2026-07-13 09:41:42 View source (.md) rev 2