Skip to content

Sources

diegokoes edited this page Jul 5, 2026 · 1 revision

Sources

A source is anything that produces work items, behind a single interface (WorkItemSource in packages/core/src/sources/source.ts). To add one:

  1. Implement the interface (list items, fetch one, normalize to RawWorkItem, optionally write a private note, optionally implement redactRaw()).
  2. Register it in the entrypoints (registerSource("type", factory)).
  3. Insert a source_connections row (add_source_connection).

No schema change. The adapter is the only thing that knows the source's field shape; core works entirely against the normalized RawWorkItem.

Built-in adapters

external_id Routing Write-back Token env var
Freshdesk ticket number group_id maps to a product private notes FRESHDESK_TOKEN_<SLUG>, falling back to FRESHDESK_TOKEN
GitHub (issues) owner/repo#123 owner/repo maps to a product, via config.repos or --group; PRs are skipped not supported (GitHub comments are public, so post_private_note is refused) GITHUB_TOKEN_<SLUG>, falling back to GITHUB_TOKEN

Connections and routing

source_connections stores the connection: source_type (freshdesk, github), a unique slug, an optional base_url, and a free-form config JSONB bag for non-secret per-connection settings (GitHub's {"repos": [...]}, or the redaction switch). Tokens are never stored there: they resolve from the environment by source slug at call time.

source_product_map routes a source group (Freshdesk group_id, GitHub owner/repo) to a product, so ingested work items land under the right product and team automatically.

Source slug vs. source type

The source parameter in fetch_work_item, get_context, and post_private_note is the connection slug (for example acme-freshdesk), not the source type (freshdesk). Call list_source_connections first to get the slug.

Token resolution

sourceToken(provider, slug) normalizes the slug (uppercase, non-alphanumerics to _) and looks up PROVIDER_TOKEN_<SLUG> first, then the bare PROVIDER_TOKEN. So (FRESHDESK, acme-freshdesk) tries FRESHDESK_TOKEN_ACME_FRESHDESK, then FRESHDESK_TOKEN. A missing token fails with a message naming the exact var to set.

Notes

  • Freshdesk numeric status (for example 6) is account-specific and stored raw; tachý does not try to interpret it.
  • Freshdesk conversation entries 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.

Clone this wiki locally