pulse← back
privacy floor

not a toggle. not a setting. not negotiable.

Most observability tools start with "we collect everything; you can opt out." Pulse starts with the inverse: we collect what's safe by default, and the dangerous things never enter the system in the first place.

Below is the exact list of what's stored, what isn't, and where each guarantee is enforced. If anything below ever stops being true, that's a bug — open an issue at ashlrai/ashlr-pulse.

what Pulse never stores

  • prompts the text you sent to the LLM
  • completions the text the LLM sent back
  • user code · file contents · diffs no hunks, no patches, no source
  • stdout / stderr the agent's tool outputs aren't shipped
  • screenshots / window captures we don't observe your screen
  • keystrokes / per-key telemetry no input layer instrumentation
  • AFK / idle / typing-rhythm metrics no presence surveillance
  • commit bodies · PR descriptions · review comment text GitHub data is metadata only
Enforced at the activity_event + github_event schema layers (column absence) and at the API layer in lib/peer-share-guard.ts — peer-share creation rejects any field name in the forbidden list with HTTP 422 before the row reaches the database.

what Pulse does store

  • timestamp · session id · source · model structural metadata about each event
  • token counts (in / out / cache read / cache write) for cost and volume reporting
  • tool call counts + tool names what kinds of tools were invoked, never their arguments or output
  • repo name + git branch + project hash (sha256) the cwd is hashed before it leaves the machine
  • language for stack-mix reporting
  • commit SHA · PR number · PR state · diff line counts GitHub events as enums + integers
  • commit subject (first line, ≤200 chars) the only freeform string we record from GitHub — used solely for the activity feed
  • tokens_saved (when emitted by ashlr-plugin) how much was avoided via the plugin's caching layer
GenAI semantic conventions (OpenTelemetry). Every column maps to a public OTel attribute, so any compliant tool can ingest into Pulse and Pulse data can flow out into Datadog / Honeycomb / Grafana without rewiring.

how peer-share keeps the floor

Peer-share grants are per-peer, per-scope, per-granularity, per-field. When you share with a cofounder, you pick which columns they see. The never-store list isn't on the menu — those columns don't exist on activity_event, so they can't be in any grant's fields[] array even if a malicious client requests them.

Default is private. Sharing is explicit, asymmetric, and revocable. Revoking is a UPDATE on peer_share.revoked_at — the next dashboard render and the next viewer query won't surface that grant.

encryption + secrets

GitHub access tokens are encrypted at rest with AES-256-GCM via lib/token-crypto.ts. Personal Access Tokens (used by the Rust agent + ashlr-plugin) are stored as SHA-256 hashes — we cannot reproduce the plaintext after creation; you see it exactly once at mint time.

All HTTP traffic is TLS. Cookies are HttpOnly + SameSite=Lax. We never log request bodies — they may carry OTel payloads which are metadata-only by design but the principle of least logging still applies.

open source · self-hostable

The core is MIT-licensed at github.com/ashlrai/ashlr-pulse. You can run Pulse against your own Postgres + Supabase project. The hosted version at pulse.ashlr.ai is the same source, deployed on Railway. Choose the trust model that fits.

Found something we missed? File an issue or PR. The schema, the guard, and this page should stay in sync. If they ever drift, this page is wrong — open an issue.