Security
This page describes a self-hosted Watcher deployment's data flows, for security and compliance review.
What is collected
The Watcher client records coding-agent sessions. A recorded session contains:
- The full conversation: user prompts, assistant replies, the system prompt, and tool calls with their arguments and results. Tool results include whatever the agent read or produced, so transcripts can contain source code, file contents, and any secrets the agent encountered.
- Which agent produced the session (Claude Code or Codex), timestamps, and the developer's identity. In proxy mode this is the identity header your proxy injects; in SSO mode it comes from the SSO sign-in. See authentication mode.
- Blocking review decisions: the tool context, score, and outcome for each reviewed call.
- Grades: the scores, explanations, and summary text produced by graders.
Watcher does not record the screen, keystrokes, or terminal contents; the client captures only terminal identifiers (terminal program, tty, session IDs) so its UI can focus the right window. It records what the agent did, not what the developer did outside the agent.
Where it is stored
The durable copy of the recorded sessions, decisions, and grades lives in your deployment's Postgres database, the bundled Docker Postgres or the managed Postgres you configured. The terminal-focus identifiers stay on the client and are not uploaded. Operations covers server backups; the state on each developer's machine is covered on the client page.
Which LLM providers are called
All LLM grading runs from your Watcher deployment, never from developer machines. Blocking review's triage and deep review send the transcript excerpt under review from the client to your deployment, which calls the grading model; trailing review grades server-side the same way.
The API makes provider calls. The grading scheduler triggers server-side grading and needs database access, but it does not hold provider keys.
The scheduler does hold database credentials. Each pass connects to Postgres
to list the organizations to grade, then calls the API for each one; it reads
no session content. Include it when you inventory which containers receive
database credentials, and allow it a route to Postgres when you restrict
network or database access. If a policy blocks that connection, the scheduler
logs async grading sweep failed and retries on the next interval, and
trailing review stays stopped until you restore access.
The xylon-retention-cleanup container also holds database credentials and
runs the xylon-api image with a dedicated entrypoint. It contacts no LLM
provider. It connects to Postgres to delete expired unlinked grader inputs and
to enforce any enabled organization session-content retention policy. That
policy is disabled by default. Organization administrators configure it through
the Analyzer's Data Retention controls
or the organization settings API. If the worker cannot reach Postgres, it logs
the failed sweep and retries on the next interval.
Graders name provider-qualified models across Anthropic, Google, and
OpenAI. The standard grading path uses Anthropic and Google. Role-based
monitoring uses all three: Anthropic for Gateway and Deep Review, OpenAI for
Triage, and Google for session summaries. What a grading call sends to the
provider is session content: prompts, agent output, and tool results. You
supply the provider API keys, so provider choice, accounts, and data-processing
terms are yours. You can override monitor models in server-config.yaml when
your deployment uses a different provider set.
Self-hosted Watcher does not phone home
The stack sends no usage analytics, error reporting, or other telemetry to Apollo. It makes these outbound connections when configured:
- LLM APIs: grading sends session content to the configured model providers.
- WorkOS: in SSO mode, the API uses WorkOS for sign-in, token management, and organization membership. Proxy mode does not use it.
- Slack: if an administrator configures a webhook, notifications send the grader's finding, scores, and an Analyzer link. Blocking-review alerts can also contain tool arguments, paths, or secrets.
Installation and upgrades pull server images from a container registry and client files from a public release or internal mirror. These requests contain no session data. See Supply chain security for internal mirror options.
The Watcher client sends session data only to the backend recorded during installation. The deployment example shows these connections.
Admin access auditing
Admins can see every user's sessions through the
Analyzer, so the deployment keeps the reciprocal
record: an admin audit log, on by default,
appending one JSON line for each read of another user's session data,
each session list or search request, user-directory reads, and
organization-level settings writes. Session-content scrubs are always
recorded. Administrator actions carry the actor's email; automatic retention
uses retention-policy as the actor and system as the authentication method.
Records carry resource identifiers, never session content. The file stays on
the deployment host in a Docker volume, is not collected by the support
bundle, and is itself personal data to handle accordingly.
Operations covers enabling, reviewing,
and pruning it.
Retention and deletion
By default, Watcher retains session content indefinitely. An administrator can
remove the stored content of one session with
DELETE /api/v1/sessions/{session_id}/content. The operation removes the
session's messages, tool calls, linked blocking-review decisions, and linked
blocking-review grades from the active Postgres database.
The server also supports an organization-level inactive-session retention
policy. It is disabled by default, so session content is retained indefinitely.
Organization administrators can enable it from the Analyzer's
Data Retention controls
or with PATCH /api/v1/organization/settings. The configured inactivity period
must be between 7 and 365 days; setting it to null disables the policy. The
always-on retention worker removes content from sessions whose latest recorded
activity is at least the configured number of days old. The worker runs
immediately at startup and every 24 hours thereafter.
The scrub retains the session record, its historical activity dates and message count, trajectory grades, notifications, and content-free activity history. A later full upload of the same session can restore its messages and reconnect retained trajectory grades, so a scrub is not a tombstone that blocks re-upload.
A blocking-review grade whose corresponding decision has not yet arrived is not attributable to a session and cannot be removed by this session-specific operation. Watcher's always-on retention worker makes these unlinked grader inputs eligible for deletion after eight days, then deletes them on its next sweep. Linked grades and session content outside an enabled policy remain until an administrator scrubs the session. Scrubbing and the retention worker do not alter source files, client-local state, external copies, or existing backups.
Saved managed client settings documents are also retained as an append-only version history.
Retention beyond these session-content and orphan-grade policies is yours to implement with standard database tooling. Backups remain under your control (see Operations).
On developer machines, watcher uninstall removes the hooks and the binary
but intentionally keeps the local state under ~/.apollo_monitor/,
printing a reminder to remove it manually. Uninstalling a client never
touches the data already uploaded to the deployment.