---
title: Security
description: What content reaches an exporter, and what never reaches the repository
---

# Security

## Content is exported on purpose

User prompts, assistant messages, tool input and tool output all ship to the log and trace sinks.
Anything an agent printed, including a secret it happened to read, can land in the log store. This
is a deliberate choice for a private single-tenant deployment. `logs.record_types` is the control:
listing only the bodiless kinds gives an event timeline with no content.

## Content never reaches the repository

Two guards, neither of which may be weakened:

- `TestNoTranscriptsAreTracked` fails the build if anything transcript-shaped is staged. The
  `.gitignore` covers the corpus tree **and** the file extensions wherever they land, because a
  sample copied to a new path is the failure mode that actually happens.
- `TestSignature_CarriesNoConversationContent` proves the committed drift baseline holds field
  names and types only, never a value from a transcript.

`backlog/` is committed, so the same bar applies there: write the shape, not the instance. A task
that quotes a real prompt to illustrate a decoder bug is a leak.

## Cardinality is a safety property, not just a cost one

A metric attribute is indexed and retained differently from a log attribute. Identifiers and content
are confined to logs and spans, where they ride as unindexed attributes. The rule is enforced in
`internal/attr` rather than by convention, so a new field cannot reach a metric without a deliberate
classification.

## The transcript trees are read-only

The service opens them read-only and never writes, renames, locks or prunes. Retention is owned by
`agent-session-archive.timer` on camden, and this service is not part of that chain. Its checkpoint
lives outside the tree.

## Credentials

The OTLP endpoint is the local Alloy on camden, which holds the Grafana Cloud credential through
Fleet Management. This service carries no Grafana credential. If `otlp.headers` is ever set, it goes
in `config.yaml`, which is gitignored; never in `config.example.yaml`.
