← All needs

Redact tool_uses and pending_messages at insert time

## Problem claude-mem stores tool payloads verbatim. `tool_uses.tool_input` / `tool_response` and the `pending_messages` queue copy the hook payload, so a credential that a harness redacts on the model-facing path still lands in the database. Prompts are already redacted at insert; tool payloads are not. ## Evidence (15.4.0, `scripts/worker-service.cjs`) - `tool_uses` insert passes `rFe(e.toolInput)` / `rFe(e.toolResponse)`. `rFe` truncates on byte length and appends `…[truncated: N bytes]`; it does not redact. - `saveUserPrompt` passes `prompt_text` through `zg` → `jr` → `tvt` → `UAe` → `DN`, so prompts *are* redacted when `CLAUDE_MEM_REDACT_ENABLED=true`. That is the pipeline to reuse. - `storeObservations` / `storeSummary` insert fields raw; they are only as clean as the observer input, which the same flag redacts. - Sync-apply (`applyObservation`, `applyPrompt`) passes values through `rr`, which is `typeof t === "object" ? JSON.stringify(t) : t ?? null` — normalisation only, no redaction. - `pending_messages` receives the same raw tool payloads as `tool_uses`. - Flag defaults: `CLAUDE_MEM_REDACT_ENABLED="false"`, `CLAUDE_MEM_REDACT_GENERIC_ENABLED="false"`. So enabling redaction today protects prompts and observer-derived memory, but leaves the raw tool store and imported rows untouched. ## Proposal 1. Redact `tool_input` / `tool_response` in `tool_uses` and `pending_messages` through `DN`, gated by `CLAUDE_MEM_REDACT_ENABLED`. 2. Apply the same treatment on the sync-apply path (`rr` call sites), so imported rows cannot reintroduce what local writes removed. 3. Extend the built-in rule set, or document `CLAUDE_MEM_REDACT_CUSTOM_PATTERNS` as the supported way to reach parity with the 220-rule corpus harnesses ship. Current built-ins cover generic password/token, bearer, and AWS secret/session; they do not cover Stripe, GitHub, Slack, Hugging Face, GCP, Sourcegraph, Linear, PEM blocks, JWTs, URL passwords or Basic auth. 4. Fail closed: withhold a row whose scrub throws, rather than storing it raw. ## Risks - **`content_hash`.** `tool_uses.content_hash` is `sha256(tool_name, tool_input, tool_response)` truncated to 16 hex characters. Redacting at insert changes the hash and therefore dedup identity. Decide whether the hash is computed before or after redaction, and document it. - **Performance.** Regex work over payloads that can be hundreds of kilobytes, on every tool call. Bound the scan and skip rows above a ceiling explicitly rather than silently. - **Markers inside JSON.** ` ` markers inserted into a JSON tool payload must be applied to parsed values, not raw text, or the stored payload stops parsing. - **Retroactivity.** The change does not clean existing rows; document a migration path. ## Acceptance criteria - A tool call carrying a vendor credential stores a placeholder in `tool_uses.tool_input`/`tool_response`, and the cell still parses as JSON where it did before. - `pending_messages` behaves the same. - Sync-applied rows are redacted, or the path is explicitly documented as trusted-only. - Tests cover JSON payloads, oversized payloads, already-redacted input (idempotent), and the flag being off.