Privacy modes

Talos Auditor ships four data-handling modes. The default is the most conservative — prompt text never leaves the developer's machine. Admins can upgrade to higher-signal modes per team.

For the full trust statement see the Trust page. This doc is the short engineering explainer.

Quick comparison

ModePrompt textStored contentAI costUse when
offNever leaves machineNone$0Strict IP / compliance
categorize-localNever leaves machineStructured output only$0"What are they working on?" with zero egress
categorize-cloudTouches CF edge, GC'dStructured output only~$0.002 / promptEasier setup, no local Ollama
fullUploaded, stored in R2Full prompt + completionSession drill-down / debugging

What "never leaves the machine" means

In off and categorize-local modes, the agent strips content from every event before the HTTP client ever sees the payload. This is enforced in apps/agent/src/redactor.ts. Even if the server mistakenly queried the old mode, the plaintext is gone by the time bytes hit the socket.

The server also enforces the current mode (defense-in-depth). The consumer Worker refuses to write prompt text to R2 when privacy_mode !== "full", and refuses to call Haiku when privacy_mode !== "categorize".

Categorize output

Regardless of local or cloud, both categorize modes produce the same structured output and store only that in D1:

{
  "category": "feature-dev | bug-fix | refactor | docs | test | exploration | review | ops | unknown",
  "taskHint": "Short noun phrase — no code, no secrets (max 120 chars)",
  "projectHint": "Inferred project or feature (max 60 chars)",
  "confidence": 0.87
}

The manager-facing dashboard shows these aggregated by developer and by category — so you get "Alice: 45% feature-dev on 'billing revamp', 30% bug-fix" without ever storing her actual words.

Changing modes

Admins change privacy mode in /dashboard/settings/team. The running agent picks up the change within 60 seconds via its heartbeat ping — no restart required. When dropping from full to a tighter mode, the agent stops sending content immediately.

Retroactive wipe: We plan to add a "wipe archived content" button for teams that previously used full mode and want to downgrade without waiting for retention. Ships in Phase G.

What we always send

Regardless of mode, every event includes these fields so you get basic analytics:

  • Event UUID, timestamp, Claude/Cursor session ID
  • Model name, token counts (input/output/cache read/cache write)
  • Tool source (claude-code or cursor)
  • cwdHash — SHA-256 of the full working directory + your team's salt, truncated to 32 hex chars
  • cwdBasename — just the folder name, e.g. my-app. Never the full path.
  • Git branch name (if detected)

The hash-with-team-salt approach means even if we compared two teams, we couldn't correlate that they're working in the same repo.