> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usehone.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Data governance

> How to keep end-user data safe with Hone: pseudonymous identifiers, metadata allowlisting, and redacting sensitive content before it leaves your app.

Hone stores conversations so it can surface signal from them, which means the text you send may contain real user data. Hone does not scrub that content for you. Redaction and pseudonymization happen in your application, before anything is sent. This page describes the practices that keep that data safe.

<Warning>
  Hone does not remove personal or sensitive data at ingestion. Whatever you send is what gets stored. Treat every field as if it will be retained, and clean it on your side first.
</Warning>

## Use pseudonymous user ids

A `user_id` should be an opaque handle, not a piece of personal information. Map your real users to stable random identifiers and send only the handle.

<CodeGroup>
  ```python Python theme={null}
  # Good: an opaque, stable handle
  hone.identify("user_8f21", {"plan": "enterprise"})

  # Avoid: personal data as the identifier
  # hone.identify("jane.doe@example.com", {...})
  ```

  ```typescript TypeScript theme={null}
  // Good: an opaque, stable handle
  identify("user_8f21", { plan: "enterprise" });

  // Avoid: personal data as the identifier
  // identify("jane.doe@example.com", { ... });
  ```
</CodeGroup>

An opaque id still lets you group a user's conversations and follow a thread across turns. It just does not hand Hone an email or a name to store.

## Allowlist your metadata

Metadata and user traits are useful as filter and chart dimensions, but they are also an easy place for sensitive fields to leak in by accident. Decide explicitly which keys you send, and drop everything else.

<CodeGroup>
  ```python Python theme={null}
  ALLOWED_METADATA = {"plan", "region", "source", "model"}

  def clean_metadata(raw: dict) -> dict:
      return {k: v for k, v in raw.items() if k in ALLOWED_METADATA}

  hone.identify("user_8f21", clean_metadata(user_attributes))
  ```

  ```typescript TypeScript theme={null}
  const ALLOWED_METADATA = new Set(["plan", "region", "source", "model"]);

  function cleanMetadata(raw: Record<string, unknown>) {
    return Object.fromEntries(
      Object.entries(raw).filter(([k]) => ALLOWED_METADATA.has(k)),
    );
  }

  identify("user_8f21", cleanMetadata(userAttributes));
  ```
</CodeGroup>

Register the keys you intend to send under **Settings → Metadata Keys** so they become selectable dimensions, and keep that list as the single definition of what is allowed to flow.

## Redact before you send

The `input` and `output` you capture are free text and often the highest-risk fields. Run them through a scrubber that masks the categories of data you know appear in your product, such as email addresses, phone numbers, and payment details.

<CodeGroup>
  ```python Python theme={null}
  import re

  PATTERNS = {
      "[email]": r"[\w.+-]+@[\w-]+\.[\w.-]+",
      "[card]": r"\b(?:\d[ -]*?){13,16}\b",
      "[phone]": r"\b\+?\d[\d ()-]{7,}\d\b",
  }

  def redact(text: str) -> str:
      for replacement, pattern in PATTERNS.items():
          text = re.sub(pattern, replacement, text)
      return text

  hone.track(
      user_id="user_8f21",
      input=redact(user_message),
      output=redact(agent_reply),
  )
  ```

  ```typescript TypeScript theme={null}
  const PATTERNS: [string, RegExp][] = [
    ["[email]", /[\w.+-]+@[\w-]+\.[\w.-]+/g],
    ["[card]", /\b(?:\d[ -]*?){13,16}\b/g],
    ["[phone]", /\b\+?\d[\d ()-]{7,}\d\b/g],
  ];

  function redact(text: string): string {
    return PATTERNS.reduce((acc, [repl, re]) => acc.replace(re, repl), text);
  }

  track({
    userId: "user_8f21",
    input: redact(userMessage),
    output: redact(agentReply),
  });
  ```
</CodeGroup>

A regex scrubber is a floor, not a ceiling. Tune the categories to your domain, and pair it with any structured redaction you already run elsewhere.

## What not to send

Do not send secrets or regulated data through Hone without an appropriate agreement in place. That includes:

* API keys, passwords, and access tokens.
* Regulated categories such as health records, full payment card data, or government-issued identifiers.
* Documents that carry someone else's personal data, such as resumes.

## Transport

All traffic to Hone travels over HTTPS. Combined with pseudonymous ids, allowlisted metadata, and redacted text, that keeps the data both encrypted in transit and stripped of what it never needed to contain.
