SemiLayerDocs

Security model

What crosses the boundary between your network and SemiLayer, and what doesn't. Designed so you can hand this page to a security review.

Trust boundaries

DirectionProtocolContentsWho initiates
Runner → SemiLayer (WSS)TCP 443, TLS 1.3Handshake (rk_ token), job results, heartbeatRunner
SemiLayer → RunnerSame open WSSJob dispatch framesGateway pushes over the connection the runner opened
Runner → Your DBWhatever the driver uses (usually TCP + TLS)Queries, query resultsRunner
  • SemiLayer never opens an inbound connection to your network.
  • Your database never sees a TCP connection from an IP outside your network (unless you've chosen the IP allowlist path, where we connect directly with documented egress IPs).

Auth

  • rk_ tokens are generated in the Console, shown exactly once, and stored as a SHA-256 hash on our side. Rotation is instant: revoking a runner marks the api_keys row as revoked and the next frame on its open socket is refused.
  • The token is presented as a query-string parameter on the WebSocket upgrade. Combined with TLS, that's equivalent security to a bearer header (the query string is part of the encrypted path, not logged on our side).
  • Internal /dispatch calls from api.semilayer.com to the gateway use a separate shared bearer (INTERNAL_DISPATCH_TOKEN) plus VPC-only ingress. Customer traffic never reaches this endpoint.

Credentials

Two modes per source:

  • Managed (default) — SemiLayer stores the bridge config encrypted at rest (AES-256-GCM, envelope-encrypted via a managed cloud KMS on SaaS deployments). We decrypt it in process memory only, and ship it to the assigned runner over the same encrypted WebSocket described above. It never hits disk on the runner.
  • Runner-local — SemiLayer never sees credentials. See the airgap mode page.

Data

  • Query params (filters, cursors, limits) travel over the WebSocket to the runner. Same on the return path for results.
  • Result rows are shipped back in whatever shape your lens config declares via fields — we don't see the raw source row, only what your mapping exposes.
  • We log aggregates (row count, duration, error codes) in the runner_jobs ledger. We do not log result contents.

Failure modes

  • Runner compromised. An attacker with runner host access can read your DB (which was already true — the runner has to reach the DB). They cannot read other customers' data. They cannot modify queries — the dispatch frames are signed implicitly by the INTERNAL bearer the gateway validates.
  • SemiLayer compromised. An attacker with SemiLayer infrastructure access could issue dispatch frames to your runner. The runner executes them as the DB user your config uses — so that user's permissions are your failure envelope. Use a read-only role for lenses that only read.
  • WebSocket MITM. TLS 1.3 with certificate pinning blocks unauthorized intermediaries. The runner validates the certificate for runner.semilayer.com before sending the token.

Compliance posture

  • Data residency: runner + DB on your side, SemiLayer in our US East region (or your pinned region for enterprise contracts).
  • GDPR: we're a processor for query params + result rows. Airgap mode reduces scope further — we never hold credentials.
  • Audit: every dispatch creates a runner_jobs row with runner_id, kind, status, duration. Retained 90 days; exportable on request.