defmodule AgentSea.Guardrail.PIIRedactor do @moduledoc """ Redacts personally-identifiable information by rewriting the content (a `{:transform, _}` outcome). Redacts emails, US SSNs, and phone numbers by default; configure with `:types` (any of `:email`, `:ssn`, `:phone`). """ @behaviour AgentSea.Guardrail @patterns %{ email: ~r/[\w.+-]+@[\w-]+\.[\w.-]+/, ssn: ~r/\b\d{3}-\d{2}-\d{4}\b/, phone: ~r/\b\d{3}[-.\s]\d{3}[-.\s]\d{4}\b/ } @default_types [:email, :ssn, :phone] @impl true def name, do: "pii_redactor" @impl true def check(content, opts) do types = Keyword.get(opts, :types, @default_types) redacted = Enum.reduce(types, content, fn type, acc -> Regex.replace(@patterns[type], acc, "[#{String.upcase(to_string(type))}]") end) if redacted == content, do: :ok, else: {:transform, redacted} end end