-
Notifications
You must be signed in to change notification settings - Fork 0
Compliance and Redaction
An optional layer lets a deployment satisfy company AI-usage policies that forbid sending customer personal data or credentials to a model. It is off by default: with nothing configured, behavior is byte-for-byte unchanged.
Implementation: packages/core/src/compliance/redaction.ts.
Redaction happens inside the fetch_work_item and get_context tool handlers,
before any model sees the data. Because that boundary is provider-neutral, the
same protection covers Claude, an organization's own LLM, or any future consumer.
It runs after ingestWorkItem (the full-data DB write) and
resolveCustomerByEmail (email-domain matching), so:
- storage keeps the real data on your own infrastructure, and
- customer auto-matching still works.
Only the copy returned to the model is scrubbed.
Per source connection, on the existing config JSONB:
A Freshdesk tenant is roughly one company, so per-connection is the natural granularity.
Or deployment-wide: TACHY_REDACT=true, or the redaction_global
runtime setting. The deployment-wide switch also covers the
connection-less tools (ingest_context, and retrieved search results that may
carry PII saved before redaction was enabled), which have no source connection to
read a policy from.
-
Source-agnostic. Scrubs the normalized
RawWorkItemfields every adapter produces identically:requesterEmaildropped;requesterreplaced with the resolved customer slug;titleand eachmessages[].bodyTextrun through a regex scrub (emails to[EMAIL_n], phone numbers to[PHONE_n]); message authors to[USER_n]. Tokens are stable per work item (the same value maps to the same token), so referential context survives. -
Source-specific. Each adapter implements an optional
redactRaw()hook onWorkItemSourceto scrub the source-specificrawpayload, since only the adapter knows its field shape. Both layers share one token map.
| Source |
raw fields scrubbed |
|---|---|
| Freshdesk |
email, phone, name; cc_emails / to_emails / fwd_emails / reply_cc_emails; twitter_id / facebook_id; the requester embed (email / mobile / phone / name); company.name; free-text subject / description / description_text; and the values of custom_fields (keys such as cf_devops_work_item are preserved). |
| GitHub | actor login / email / name on user / assignee / assignees / closed_by; free-text title / body. |
Because the app already resolves the requester's email domain to a known
customers row, the model is shown the stable customer slug (for example
acme-corp) in place of the person's real name and email. The company signal is
preserved; the individual PII is dropped. Retrieval stays effective without
exposing a person.
Redaction is deterministic: structured fields plus email/phone regex. It does not run named-entity recognition, so a person's name typed free-form in a message body is only caught if it appears as an email or phone. All structured PII fields and all emails/phones are covered.
Redaction placeholders ([EMAIL_n], [PHONE_n], [USER_n], and the secret and
card placeholders) are intentional and opaque. The agent is instructed never to
reconstruct the originals, and never to write secrets or personal data into saved
entries or reference docs (CLAUDE.md rule 17).
Freshdesk conversation entries already only expose body_text into the
normalized messages. Per-message from_email / to_emails / cc_emails /
bcc_emails / support_email are dropped by the adapter mapping and never reach
a model, regardless of redaction mode.
tachý - self-hosted knowledge engine for work items. README · AGPL-3.0-or-later
Design
Subsystems
Platform
Security