Privacy and Security
Pulse is self-hosted. This page explains exactly what data lives where, what connects to the internet, and how the security posture is built so home users and regulated businesses can both trust it.
The one-line summary
Pulse runs on your hardware. Your data never leaves your hardware unless you explicitly send it somewhere through a configured agent.
Where your data lives
When you install Pulse, a single data directory is created (default: ~/pulse-data on Linux/macOS, %USERPROFILE%\pulse-data on Windows). Everything Pulse persists lives in that one folder:
pulse-data/ ├── pulse.mv.db ← users, orgs, sessions ├── pulse-audit.mv.db ← audit log ├── pulse-events.mv.db ← event bus + topics ├── pulse-agents.mv.db ← agent definitions ├── pulse-chat.mv.db ← chat history ├── pulse-knowledge.mv.db ← learning + RAG ├── pulse-config-store.mv.db ├── pulse-guardian-rules.mv.db ├── pulse-dlq.mv.db ← blocked events ├── pulse-pipelines.mv.db ├── pulse-uploads.mv.db ← files you uploaded ├── .jwt-secret ← session-signing key ├── .vrf-secret ← PVSC consensus key ├── .encryption-key ← master key for credentials ├── .license.jwt ← Pulse license token ├── logs/ ← rotating application logs ├── backups/ ← automatic snapshots └── user-templates/ ← your custom templates
Back up the folder, you back up Pulse. Delete it, you've removed every trace. Nothing outside this folder is ever touched, not your system keychain, not the registry, not the cloud.
What connects to the internet
Pulse makes outbound calls for four reasons. You can disable each one for fully offline operation.
LLM API calls
Only when YOU configure a cloud provider. Set the LLM provider to a local runtime and Pulse never contacts any vendor. Cloud prompts travel directly between Pulse and the vendor; the license server never sees them.
MCP plugin calls
When an agent uses a tool you wired up (Slack, SMTP, an API…). The destinations are the ones you chose.
Daily update check (optional)
Once a day Pulse polls the public GitHub releases feed. Sends only a User-Agent. Disable with update.checkEnabled: false.
Weekly license refresh (optional)
Once a week Pulse calls license.streamflowmesh.io/refresh?licenseId=X. Sends only your license ID, no email, no data, no usage signals. Disable by blanking license.serverUrl.
Those are the only four. No telemetry, no analytics, no ping-home on launch. We don't know how many Pulse installs exist. We don't want to.
Air-gapped operation
Pulse can run with zero internet access:
- Install the binary from a USB key, no network required.
- Configure LLM to a local runtime (model download needs a one-time connection; then fully offline).
- Set update.checkEnabled: false to disable update polling.
- Set license.serverUrl: "" to disable license refresh. Paste a token once; it works for its validity period.
In this mode Pulse makes no outbound calls whatsoever. Ideal for clinical research, classified government and industrial control environments.
Network exposure
By default Pulse binds to 127.0.0.1:9090, loopback only. Only software on the same machine can reach it. No other computer on your network sees it unless you change the binding.
Opening up to a LAN
Edit pulse-config.yaml:
server: host: 0.0.0.0 # accept from any interface port: 9090
Only do this if you understand the implications. Anyone on your LAN who can reach port 9090 sees the Pulse login page. Pulse's authentication (username + password, optional 2FA) is your only defense.
Reverse proxy with TLS (recommended)
For any non-localhost exposure, put Pulse behind a reverse proxy that handles TLS:
[external] --HTTPS--> [Caddy / nginx / Cloudflare] --HTTP (loopback)--> [Pulse]
Caddy example (Caddyfile):
pulse.yourdomain.com {
reverse_proxy localhost:9090
}Caddy handles Let's Encrypt automatically. Pulse stays on loopback; the proxy is the internet-facing surface.
Credential encryption at rest
Pulse stores a lot of sensitive credentials on your behalf: SMTP passwords, API keys, OAuth tokens, database connection strings. All of them are encrypted on disk using AES-256-GCM with a master key derived from .encryption-key (generated once on first boot, stored 0600 in your data directory).
- If someone gets your database files but NOT .encryption-key, the credentials are opaque.
- If someone gets both, they have everything. Protect the master key, back it up alongside the data, or split the backup (keys in one vault, data in another).
- The master key never leaves your machine. It is not derived from your password or anything revealable.
Authentication & sessions
Password storage
Argon2id (64 MB memory, 3 iterations, 1 parallelism, well above OWASP 2025 baseline). Hashes never reverse; brute force costs ~1 s per guess.
Sessions
JWT access tokens signed with HMAC-SHA256 via .jwt-secret (256-bit). Access expires after 15 min; refresh up to 7 days. Sign-out invalidates the refresh token server-side.
2FA / TOTP
Optional per-user TOTP (Google Authenticator, 1Password, Authy…). Enable from Settings → Security. Secret encrypted with the master key.
Rate limiting
Login: 5 attempts / 15 min per IP. API calls per user + role with configurable thresholds. Enforced in-process, sufficient for single-node Pulse.
CSRF protection
State-changing endpoints require a double-submit CSRF token. Tokens rotate per session and are bound to the user ID.
Audit log
Every sensitive action is logged. The log is append-only (writes but never updates).
Retention by plan
| Plan | Audit log retention |
|---|---|
| FREE | 30 days |
| PRO | 365 days |
| ENTERPRISE | Unlimited |
Admins search, filter and export (CSV/JSON) via Settings → Audit. Useful for incident forensics, compliance, and anomaly detection.
Backups & disaster recovery
Automatic snapshots
Pulse takes a consistent snapshot of every H2 database on a schedule (default: daily, retain 7). Each snapshot is downloadable as a single zip.
Included in backups
- • User accounts (hashed passwords + 2FA state)
- • Agent definitions
- • Pipeline definitions
- • Chat history
- • Event history (subject to retention rules)
- • Audit log
NOT in a backup
.jwt-secret, .vrf-secret, .encryption-key, these are secrets, NOT data. You MUST back them up separately to a different destination (password manager, HSM, encrypted off-site storage). Without them, a restore won't work.
Restore, stage-then-apply-on-boot
- 1Upload a backup zip via Settings → Backups → Restore from file (or pick a local snapshot).
- 2Pulse validates the manifest + version compatibility.
- 3Staging directory is populated with the unpacked .mv.db files.
- 4A "Restore pending" banner appears.
- 5Restart Pulse. On boot, before any JDBC connection opens, the staged files replace the live ones.
Why stage-then-apply? H2 memory-maps its database files; hot-swap corrupts the page cache. Stage-and-restart is the only safe approach.
Runtime safeguards
Single-instance guard
OS-level file lock (.pulse.lock) prevents two Pulse installs from corrupting the same data directory. A second Pulse exits with code 75 (EX_TEMPFAIL) and supervisors won't loop.
Graceful shutdown
On SIGTERM Pulse stops accepting requests, drains in-flight, cancels schedulers, flushes subscribers, issues SHUTDOWN to each H2 connection, releases the lock. Each step has a 10-second timeout.
Watchdog
Every 5 minutes a daemon compares "agents the DB says are running" vs "agents actually subscribed". On drift, it re-subscribes and logs the recovery. autoRecover: false available for strict change-control.
Supply-chain posture
- Pulse is distributed as a single signed binary, a SHA-256 checksum accompanies every release. Verify before installing.
- The binary is built in a reproducible environment (Maven + Eclipse Temurin JDK 25). Same source, same binary.
- We don't embed analytics SDKs, telemetry libraries, or any third-party code that phones home.
- Upstream dependencies (Jackson, Logback, H2, Jetty, Jakarta Mail) are pinned to known-good versions and bundled rather than downloaded at runtime.
Compliance notes
Pulse is not formally certified for any regime (HIPAA, SOC 2, PCI-DSS, GDPR). What we provide instead:
- Architectural support for compliant workloads: self-hosted, audit log, credential encryption, air-gap capable, fine-grained retention.
- Documentation you can hand to your security / compliance team.
- Configurability to adjust to your regime's specific requirements.
GDPR
Right to erasure: build a custom pipeline that deletes a user_id across every topic. Data residency: Pulse runs where you run it. Consent: the consent-tracker premium template handles it.
HIPAA
Deployable HIPAA-compliant with local-only LLM, guardian rules to block PHI egress, audit log retention, and user access controls. See medical-xray-triage as reference. You are the Covered Entity; Pulse is software.
SOC 2
Audit log, encrypted credentials at rest, multi-user with roles, and 2FA cover most controls. ENTERPRISE typically adds SSO + fine-grained ACLs.
ENTERPRISE customers can request custom legal terms (DPA, security letters). The self-hosted model means Pulse is not a processor of your data in the GDPR sense.
Reporting security issues
Found a vulnerability? Email security@streamflowmesh.io with:
- • Description of the issue
- • Steps to reproduce
- • Affected Pulse version
- • Your contact info
Our commitments
- Acknowledge within 48 hours.
- Provide a remediation plan within 7 days for high-severity issues.
- Credit the reporter in the release notes (if they want credit).
We don't run a bug bounty today, but genuine high-impact findings on production-affecting code paths receive compensation, get in touch.
Email security team