Skip to main content

Offline Behavior and Network Calls

This page documents what the ssg CLI and daemon do when there is no network, what degrades, and how you can confirm that a rule evaluation makes no network call on your own machine. Air-gapped use is not supported and is not verified: every governed path needs a verified paid license JWT (see the license boundary below). The background-call list below is derived from the shipped Go runtime (sigmashake-gov/go). The Go source files that support each call are listed at the end of this page.

Note 2026-10-11: an earlier version of this page described a usage heartbeat every 2 minutes, an automatic audit sync every 5 minutes and a telemetry POST. Those calls exist only in the legacy TypeScript daemon. The shipped Go daemon does not make them. The page is re-derived from the Go source.


What needs no network call per tool call​

Rule evaluation is local: it makes no network call for each tool call. The ssg eval engine (pure-Go in-process, go/internal/goengine) loads rules from the local SQLite database at ~/.sigmashake/rules.db and evaluates every tool call in-process. No external binary or shared library is required — the Go engine runs entirely within the ssg process with no subprocesses on the eval hot path.

Nothing in this chain requires a network call by default. A DENY, ALLOW, or ASK decision is computed locally and returned to the calling agent before any network I/O could occur. The one exception is the opt-in Jev assist (bring-your-own TypeSafe key): when it is on and a key resolves, ssg eval sends the tool name and input to api.typesafe.ai, and an Ask result can override a local Allow.

What you can verify yourself. With the daemon running, run a dry-run probe with all network interfaces disabled (or while capturing traffic — see the self-test section below):

ssg probe hook --tool=Bash --input='{"command":"ls -la"}'

The command returns a governance decision. If it returns a decision, local eval is working. If the binary itself is unavailable, see the degraded-mode section.

The daemon (ssg daemon) makes no network call to load rules, evaluate tool calls over a Unix socket, or write audit rows to local SQLite. Its background tickers (license heartbeat, fleet heartbeat) do use the network, as listed below.

The dashboard (ssg serve) serves the governance UI at 127.0.0.1:5599. The dashboard SPA and all its assets are embedded in the binary. Loading the dashboard does not make external network calls. The dashboard itself reads state from the local daemon over loopback, so it loads without a network as long as the daemon is running.

The license boundary​

Every value surface needs a verified paid license JWT that accounts.sigmashake.com issues. This applies to ssg eval, the PreToolUse hook, the daemon and the offline hook fallback. Without a verified license, the check is fail-closed: every call is blocked with Pro license required. See Plans and limits.

  • The license JWT lasts 30 days for Pro and 90 days for Enterprise.
  • The daemon refreshes it about every 6 hours, when it can reach accounts.sigmashake.com.
  • The CLI keeps accepting the JWT for 7 days after it expires. After that, the machine has no valid license and blocks every call.

A machine with no route to accounts.sigmashake.com therefore works only until the last JWT it holds is 7 days past expiry. Revoking a token or unpairing a device stops new license mints only. An already-issued JWT keeps working until it expires.


What makes background network calls and when​

The daemon runs several background tickers. All are fire-and-forget and non-fatal — a network failure never blocks or fails an evaluation.

License heartbeat (licensed tier only)​

  • Endpoint: https://accounts.sigmashake.com/api/v1/license/heartbeat
  • Cadence: every 6 hours (with about 10 % jitter)
  • Payload fields: jwt (your license JWT), fingerprint (the one-way SHA-256 machine fingerprint), version, daily_eval_count
  • Trigger condition: only fires when a license JWT exists at ~/.sigmashake/license.jwt (i.e., you have a Pro or Enterprise license)
  • What happens offline: the POST fails silently and the next tick retries. The daemon continues with the last successfully verified tier.

The account service pairs the fingerprint with your account on a valid heartbeat. No tool-call content, file paths, source code, credentials or rule bodies are in the payload.

Tier behavior when heartbeat cannot reach the server. The license JWT already contains your tier claim. The daemon re-reads the JWT from disk. As long as the JWT has not expired, your tier is preserved locally without a successful heartbeat. Revocation requires a successful heartbeat response with status: "revoked" to take effect. It is never applied speculatively offline.

No usage heartbeat​

The shipped Go daemon sends no separate usage heartbeat. Unlicensed installs send no heartbeat to accounts.sigmashake.com. Only the license heartbeat above carries the daily evaluation count, and only when a license JWT exists.

Fleet heartbeat (fleet-enrolled devices only)​

  • Endpoint: https://fleet.sigmashake.com/api/v1/agents/heartbeat (the SSG_FLEET_API_URL environment variable overrides the host; the daemon accepts only https, or http for loopback addresses)
  • Cadence: every 5 minutes. After a failure the retry delay doubles from 30 seconds up to the 5-minute interval.
  • Payload fields: agent_id, policy_version, ssg_version. The agent JWT goes in the Authorization header.
  • Trigger condition: only fires when an agent JWT exists at ~/.sigmashake/agent.jwt, which ssg fleet enroll writes.
  • What happens offline: the POST fails and the daemon retries with the back-off above. The server returns a rotated agent JWT (1 hour TTL) that the daemon writes to agent.jwt. Without a successful heartbeat, the JWT expires.

Telemetry​

The shipped Go runtime has no telemetry send path. ssg telemetry only shows or changes the local opt-in flag in ~/.sigmashake/telemetry.json. The Go hot path for evaluation never reads that file. The default state is opted out.

ssg telemetry # show the current state
cat ~/.sigmashake/telemetry.json
# opted_in: false means the opt-in flag is off.

Audit sync (Enterprise only, on demand)​

  • Command: ssg audit-sync (no background timer runs it in the Go daemon)
  • Endpoint (default): https://hub.sigmashake.com/api/v1/audit/sync
  • Endpoint (override): the --url flag or the SSG_AUDIT_SYNC_URL environment variable
  • Trigger condition: only runs when you run it, when a license JWT or fleet enrollment file exists, and when a hub auth token exists.
  • Payload fields: batches of audit rows, each containing timestamp, tool, capability, decision, rule_id, input_summary (truncated to 200 characters, never the full tool input), client, ssg_version.
  • What happens offline: the command fails. Unsynced rows stay in the local SQLite audit log and the next run sends them.
  • Retention: SigmaShake does not enforce one cloud audit-retention period across all stores. Cloud audit logs are available on the Enterprise plan only. Pro and free plans do not sync audit rows to SigmaShake servers; their audit log stays on the local device. Fleet deletes its own audit events daily after the per-organization audit_retention_days (default 90). No cold tier exists. See the DPA (section 10) for the full table. Dated note 2026-10-13: this replaces earlier text that said no enforced limit existed.

Update check​

  • Endpoint: https://download.sigmashake.com/cli/latest.json
  • Cadence: the CLI refreshes a local cache at startup when the cache is more than 24 hours old; skipped entirely when SSG_NO_UPDATE_CHECK is set
  • Timeout: 3 seconds (fire-and-forget; does not block evaluation)
  • What happens offline: fails silently. No upgrade prompt is shown.

Hub pull​

  • Endpoint: https://hub.sigmashake.com/api (ruleset bodies come only from the license-gated hub API). The signed manifest on raw.githubusercontent.com/sigmashakeinc/rules is read only when SSG_HUB_GITHUB_FASTPATH=1 is set.
  • Trigger: ssg hub pull and hub-related dashboard operations
  • What happens offline: hub pulls fail with an error. Rules already installed on disk continue to work.

What degrades when offline​

FeatureOffline behavior
Rule evaluation (eval/probe)Makes no network call per tool call. Needs a verified paid license JWT; without one, every call is blocked (fail-closed)
Daemon and dashboardRun locally. Governed paths need the license JWT
License tier (licensed)Preserved from cached JWT until the JWT is 7 days past expiry. After that, checks hard-block
License heartbeatSilent failure; does not affect eval
Fleet heartbeatRetries with back-off; the agent JWT expires without a successful beat
Audit cloud sync (ssg audit-sync)Command fails; rows stay local and the next run sends them
Hub rule pullsFail with an error; installed rules are unaffected
Update checksSilent failure; no upgrade prompt shown
ssg auth loginRequires network (browser OAuth / device flow)
Fleet policy pullCannot pull new policy bundle; last cached bundle applies

Self-test: prove zero egress during evaluation​

Example procedure — adapt to your environment. The commands below were not executed in producing this page; they are provided as a reproducible template for independent verification on your own machine. The ssg probe hook command itself (the subject of the test) was verified by the author.

Step 1 — capture baseline traffic​

Open a terminal and start a packet capture or proxy. On Linux with tcpdump:

# Capture all non-loopback TCP traffic to a file, run in background
sudo tcpdump -i any -w /tmp/ssg-offline-check.pcap 'not (host 127.0.0.1 or host ::1)' &
TCPDUMP_PID=$!

On macOS, replace -i any with -i en0 (or whichever interface has your default route). Alternatively, use mitmproxy or any HTTPS proxy you trust — set HTTPS_PROXY to its address before the probe command.

Step 2 — run the eval probe​

ssg probe hook --tool=Bash --input='{"command":"echo hello"}'

Expected output: a governance decision (allow, deny, or ask) with no network activity visible in the capture.

Step 3 — stop the capture and inspect​

# Stop tcpdump
kill $TCPDUMP_PID

# Inspect captured packets (should show zero rows to external hosts)
tcpdump -r /tmp/ssg-offline-check.pcap -n 2>/dev/null | grep -v '^$' | head -20

If no packets appear (or only loopback packets appear), the eval made no external network calls.

Why no network calls happen during eval (default configuration). If the opt-in Jev assist is on, ssg eval sends the tool name and input to api.typesafe.ai. Otherwise the eval path reads rules from the local SQLite database, runs them through the pure-Go in-process engine, and writes the result to the local audit log. There is no IPC to a remote service or subprocess on the critical path. The background heartbeat tickers run on their own intervals and are not triggered by an eval call. If the capture shows a license or fleet heartbeat, it came from the ticker and not from the eval.

Verifying the telemetry flag​

ssg telemetry

The Go runtime has no telemetry send path. The command shows the local opt-in flag only.


Air-gapped use (not supported)​

SigmaShake does not support air-gapped deployments and has not verified them. Do not plan an air-gapped installation on this page.

A machine with no internet access has these limits:

  • ssg auth login cannot complete (it needs accounts.sigmashake.com).
  • The license JWT cannot be issued or refreshed. When the last JWT is 7 days past its expiry, the machine blocks every governed call.
  • Hub rule pulls are unavailable (they need hub.sigmashake.com, the license-gated hub API; GitHub raw content is only the opt-in fast path).
  • Fleet heartbeats never reach the server, and the agent JWT expires.
  • Update checks never complete.

Rules that are already installed on disk keep working while the license JWT is valid. The daemon and the dashboard stay on loopback.


Honest boundary​

This document describes the network behavior of the ssg CLI and daemon as implemented in the Go runtime (sigmashake-gov/go). The legacy TypeScript source (sigmashake-gov/src) made extra calls that the Go runtime does not make. The desktop applications (SigmaShake Desktop for Linux, macOS, and Windows) embed ssg serve and the ssg binary but add their own update-check calls and desktop-platform integrations. Those behaviors are documented in the respective desktop app guides and are not covered here.

You can check each call against the Go source files listed below. Calls that this page does not list are not documented here.

Source references for the calls on this page:

ClaimSource file
Eval makes no network call per tool callsigmashake-gov/go/internal/goengine/engine.go — Engine / Engine.Evaluate (pure-Go in-process; no subprocess on eval hot path)
License heartbeat endpoint, payload (with fingerprint) and 6-hour cadencesigmashake-gov/go/internal/daemon/license_heartbeat.go
Fleet heartbeat endpoint, payload and 5-minute cadencesigmashake-gov/go/internal/daemon/fleet_heartbeat.go
No telemetry send path; opt-in flag onlysigmashake-gov/go/internal/config/telemetry_state.go, sigmashake-gov/go/internal/cli/telemetry.go
Audit sync endpoint, payload, on-demand commandsigmashake-gov/go/internal/cli/audit.go — auditRunSync()
Update check endpoint, 24-hour cache, 3-second timeout, silent failuresigmashake-gov/go/internal/cli/update_notice.go; sigmashake-gov/go/internal/cli/update.go
Hub pull endpoint and opt-in GitHub fast pathsigmashake-gov/go/internal/cli/hub.go