# Connector catalog

> This catalog is the entry point for choosing a connector, wiring its trigger manifest, and finding a ready-to-customize example. It reflects the current runtime split:

Website: https://harnlang.com/connectors/catalog.html

This page documents Harn, which is pre-1.0. Language, standard library, and CLI APIs may change. If the intended version is unclear, clarify before using this page.

---

This catalog is the entry point for choosing a connector, wiring its trigger
manifest, and finding a ready-to-customize example. It reflects the current
runtime split:

- Cron, generic webhook, A2A push, and stream ingress are core runtime
  providers.
- Provider business logic belongs in pure-Harn connector packages.
- Community connectors are Harn packages that export connector contract v1 and
  pass `harn package verify`.

For the architecture and ownership split that closes the old connector-library
epic, see [Connector architecture status](./architecture.md).

GitHub, Slack, Linear, and Notion are first-party pure-Harn packages:
`harn-github-connector`, `harn-slack-connector`, `harn-linear-connector`, and
`harn-notion-connector`. Configure one by setting
`connector = { harn = "..." }` on the `[[providers]]` table. See the
[Rust-to-Harn-package migration guide](../migrations/rust-connectors-to-harn-packages.md)
for the cutover pattern.

For an LLM-sized version of this page, use
[`docs/llm/harn-triggers-quickref.md`](../../llm/harn-triggers-quickref.md).
That file is generated from the live provider catalog and checked by CI.

## Built-in runtime providers

| Provider | Use when | Signature | Required secrets | Recipes |
|---|---|---|---|---|
| `cron` | Run scheduled local workflows. | None. | None. | Daily report, enrichment pass, health check. |
| `webhook` | Accept generic Standard Webhooks-style HTTP events. | HMAC-SHA256, `webhook-signature`, `webhook-timestamp`, `webhook-id`. | `webhook/signing_secret`. | Stripe/Square-style handlers, HMAC-gated callbacks. |
| `a2a-push` | Accept A2A task/update pushes from another orchestrator. | Transport auth is handled by the A2A layer. | None at catalog level. | Multi-orchestrator fanout, remote reviewer dispatch. |
| `kafka`, `nats`, `pulsar`, `postgres-cdc`, `email`, `websocket` | Consume stream-shaped ingress through the shared stream connector. | Provider-specific transport configuration. | None at catalog level. | Fan-in, windowing, classifier routing. |

### Cron daily report

```toml
[[triggers]]
id = "daily-digest"
kind = "cron"
provider = "cron"
schedule = "0 9 * * 1-5"
timezone = "America/Los_Angeles"
handler = "send_daily_digest"
```

See `examples/triggers/cron-daily-digest`.

### Generic webhook with HMAC

```toml
[[triggers]]
id = "stripe-webhook"
kind = "webhook"
provider = "webhook"
match = { path = "/hooks/stripe", events = ["invoice.payment_succeeded"] }
handler = "handlers::on_webhook"
dedupe_key = "event.dedupe_key"
secrets = { signing_secret = "webhook/stripe-signing-secret" }
```

See `examples/triggers/webhook-generic-hmac`.

### A2A fanout

```toml
[[triggers]]
id = "reviewer-fanout"
kind = "a2a-push"
provider = "a2a-push"
match = { events = ["task.completed"] }
handler = "route_review_result"
```

See `examples/triggers/a2a-reviewer-fanout`.

## First-party pure-Harn packages

Each first-party connector repo should publish:

- repository URL and package install command
- `harn package verify` command
- required secrets and provider scopes
- supported trigger/event types
- mocked fixtures so CI does not need live provider credentials

| Provider | Package repo | Install | Package gate | Required secrets/scopes | Supported trigger/event types |
|---|---|---|---|---|---|
| GitHub | <https://github.com/burin-labs/harn-github-connector> | `harn add github.com/burin-labs/harn-github-connector@v0.4.0` | `harn package verify . --provider github` | Webhook secret; for outbound, GitHub App id, installation id, and private key. App permissions depend on methods: issues, pull requests, contents/metadata, checks, deployments. | `issues`, `pull_request`, `issue_comment`, `pull_request_review`, `push`, `workflow_run`, `deployment_status`, `check_run`, `check_suite`, `status`, `merge_group`, `installation`, `installation_repositories`; outbound REST/GraphQL escape hatches. Each event also exposes the connector's stable `github.<event>[.<action>]` topic plus normalized `repo`/`repository` fields. |
| Slack | <https://github.com/burin-labs/harn-slack-connector> | `harn add github.com/burin-labs/harn-slack-connector@v0.2.1` | `harn package verify . --provider slack` | Signing secret; for outbound, bot token. Typical scopes: `app_mentions:read`, `channels:history`, `reactions:read`, `chat:write`, `reactions:write`, `users:read`, `files:write`. | URL verification, `message`, `app_mention`, `reaction_added`, `app_home_opened`, `assistant_thread_started`; outbound Web API calls. |
| Linear | <https://github.com/burin-labs/harn-linear-connector> | `harn add github.com/burin-labs/harn-linear-connector` (currently unreleased, manifest `0.0.0`) | `harn package verify . --provider linear` | Webhook signing secret; optional API key/access token for outbound GraphQL. | `Issue`, `Comment`, `IssueLabel`, `Project`, `Cycle`, `Customer`, `CustomerRequest`; outbound GraphQL. |
| Notion | <https://github.com/burin-labs/harn-notion-connector> | `harn add github.com/burin-labs/harn-notion-connector@v0.1.1` | `harn package verify . --provider notion --run-poll-tick` | Webhook verification token; outbound API token. Notion integration capabilities depend on pages/databases/comments used. | Webhook events such as subscription verification, page updates, comments, data source schema updates; `poll_tick` database/page watchers; outbound Notion API via `notion-sdk-harn`. |
| GitLab | <https://github.com/burin-labs/harn-gitlab-connector> | `harn add github.com/burin-labs/harn-gitlab-connector@v0.1.0` | `harn package verify . --provider gitlab` | Webhook signing secret (plain shared-secret `X-Gitlab-Token`, not HMAC); for outbound, an OAuth2 access token, PAT, or project/group access token with `api` scope. | `push`, `tag_push`, `merge_request`, `note`, `issue`, `pipeline`; outbound REST (notes, MR update/changes/approve, commit status, repository files), GraphQL passthrough, OAuth2 helpers, and shared `GitForgePullRequestEvent` emission for merge requests. |
| Forgejo | <https://github.com/burin-labs/harn-forgejo-connector> | `harn add github.com/burin-labs/harn-forgejo-connector@v0.1.0` | `harn package verify . --provider forgejo` | Webhook signing secret verified as HMAC-SHA256 from `X-Gitea-Signature`; for outbound, a user, organization, or repository access token accepted by the instance API. | `push`, `pull_request`, `issues`, `issue_comment`, `release`, `repository`, `star`; outbound REST for comments, PR updates, commit statuses, repository contents, raw API passthrough, and shared `GitForgePullRequestEvent` emission for pull requests. |
| Gitea | <https://github.com/burin-labs/harn-gitea-connector> | `harn add github.com/burin-labs/harn-gitea-connector@v0.1.0` | `harn package verify . --provider gitea` | Webhook signing secret verified as HMAC-SHA256 from `X-Gitea-Signature`; for outbound, an access token scoped to the target self-hosted instance. | `push`, `pull_request`, `issues`, `issue_comment`, `release`, `repository`, `star`; outbound REST for comments, PR updates, commit statuses, repository contents, raw API passthrough, and shared `GitForgePullRequestEvent` emission for pull requests. |
| Bitbucket | <https://github.com/burin-labs/harn-bitbucket-connector> | `harn add github.com/burin-labs/harn-bitbucket-connector@v0.2.0` | `harn package verify . --provider bitbucket` | Optional webhook signing secret verified as HMAC-SHA256 from `X-Hub-Signature`; `X-Hook-UUID` and `X-Request-UUID` are preserved for dedupe. For outbound, app password, OAuth2 token, or Data Center PAT. | Cloud and Data Center `repo:push`, `pullrequest:*`, `issue:*`, `repo:commit_status_*`; outbound PR comments/updates, commit statuses, repository file fetches, and raw API passthrough. |
| CircleCI | <https://github.com/burin-labs/harn-circleci-connector> | `harn add github.com/burin-labs/harn-circleci-connector@v0.1.0` | `harn package verify . --provider circleci` | Webhook signing secret verified as `circleci-signature` `v1=` HMAC-SHA256 over the raw body; for outbound, a CircleCI personal API token sent as `Circle-Token`. | `workflow-completed`, `job-completed`; failure normalization, workflow rerun from failed, cancel, workflow/job lookups, and artifact listing. Use the shared GitHub commit-to-PR resolver when the webhook has no PR number. |
| Buildkite | <https://github.com/burin-labs/harn-buildkite-connector> | `harn add github.com/burin-labs/harn-buildkite-connector@v0.1.0` | `harn package verify . --provider buildkite` | Preferred webhook verification is `X-Buildkite-Signature: timestamp=...,signature=...` HMAC-SHA256 over `"<timestamp>.<raw_body>"` with a 5-minute freshness window; `X-Buildkite-Token` is accepted as a simpler fallback. Outbound calls use `Authorization: Bearer`. | `build.finished`, `job.finished`; failure normalization, job retry, rebuild, cancel, job log fetches, raw REST, optional GraphQL, and shared GitHub commit-to-PR lookup when `build.pull_request` is absent. |
| SourceHut | <https://github.com/burin-labs/harn-sourcehut-connector> | `harn add github.com/burin-labs/harn-sourcehut-connector@v0.1.0` | `harn package verify . --provider sourcehut` | Webhook public key verified with Ed25519 over the raw payload; outbound GraphQL/REST calls use an OAuth2 token or PAT. | Repository push/update events, todo/ticket changes, build notifications, mailing-list oriented message metadata; outbound GraphQL/REST passthrough. |
| Subversion | <https://github.com/burin-labs/harn-svn-connector> | `harn add github.com/burin-labs/harn-svn-connector@v0.1.0` | `harn package verify . --provider svn --run-poll-tick` | Optional post-commit hook HMAC secret; polling credentials are repository URL plus username/password, SSH key, or ambient host-managed credential helper. | `commit`, `branch`, `tag`, `property_change`; webhook-style post-commit normalization plus `poll_tick` revision scanning for repositories that cannot install hooks. |

Direct GitHub installs are the MVP path. Registry names such as
`@burin/notion-connector` should be used once the hosted first-party index is
available.

### GitHub stale PR nudger

```toml
[[triggers]]
id = "github-stale-pr-nudger"
kind = "cron"
provider = "cron"
schedule = "0 15 * * 1-5"
handler = "nudge_stale_prs"
```

See `examples/triggers/github-stale-pr-nudger`.

### Slack keyword router

```toml
[[triggers]]
id = "slack-keyword-router"
kind = "webhook"
provider = "slack"
match = { path = "/hooks/slack", events = ["message", "app_mention"] }
handler = "route_message"
secrets = { signing_secret = "slack/signing-secret" }
```

See `examples/triggers/slack-keyword-router`.

### Linear SLA breach alert

```toml
[[triggers]]
id = "linear-sla-breach"
kind = "cron"
provider = "cron"
schedule = "*/30 * * * *"
handler = "scan_for_sla_breaches"
```

See `examples/triggers/linear-sla-breach`.

### Notion database watcher

```toml
[[triggers]]
id = "notion-database-watcher"
kind = "poll"
provider = "notion"
handler = "on_database_change"
poll = { interval = "5m", state_key = "notion:database:watcher", max_batch_size = 50 }
secrets = { verification_token = "notion/verification-token" }
```

See `examples/triggers/notion-database-watcher`.

### Git forge quickstart demo

GitHub, GitLab, and Forgejo can be wired side by side with only provider
package changes. Each provider owns its verification and outbound API details
inside its pure-Harn connector package:

```toml
[dependencies]
harn-github-connector = { git = "https://github.com/burin-labs/harn-github-connector", rev = "v0.4.0" }
harn-gitlab-connector = { git = "https://github.com/burin-labs/harn-gitlab-connector", rev = "v0.1.0" }
harn-forgejo-connector = { git = "https://github.com/burin-labs/harn-forgejo-connector", rev = "v0.1.0" }

[[providers]]
id = "github"
connector = { harn = "harn-github-connector" }

[[providers]]
id = "gitlab"
connector = { harn = "harn-gitlab-connector" }

[[providers]]
id = "forgejo"
connector = { harn = "harn-forgejo-connector" }
```

## Community connector discovery

A community connector is any Harn package that:

1. Declares `connector_contract = "v1"` in package or registry metadata.
2. Provides a `[[providers]]` manifest entry with `connector = { harn = ... }`.
3. Exports `provider_id`, `kinds`, `payload_schema`, and the relevant
   `normalize_inbound`, `poll_tick`, or `call` exports.
4. Declares provider-scoped `setup` metadata for generic host setup/status UI.
5. Ships deterministic `[connector_contract]` fixtures and passes
   `harn package verify .`.

Minimal package shape:

```toml
[package]
name = "harn-acme-connector"
version = "0.1.0"
connector_contract = "v1"

[exports]
default = "src/lib.harn"

[[providers]]
id = "acme"
connector = { harn = "src/lib.harn" }
capabilities = ["webhook"]

[providers.setup]
auth_type = "api-key"
flow = "api-key"
required_secrets = [{ id = "acme/api-key", direction = "outbound" }]
credential_environment = [
  { secret = "acme/api-key", environment_names = ["ACME_API_KEY"] },
]
setup_command = ["harn", "connect", "api-key", "--connector", "acme", "--secret-id", "acme/api-key"]
validation_command = ["harn", "connect", "status", "--connector", "acme", "--json"]

[[providers.setup.health_checks]]
id = "api-key"
kind = "secret"
secret = "acme/api-key"

[providers.setup.recovery]
missing_auth = "Store an Acme API key as acme/api-key."
expired_credentials = "Rotate the Acme API key."
revoked_credentials = "Replace the revoked Acme API key."
missing_scopes = "Create an Acme API key with the required scopes."
inaccessible_resource = "Grant the API key access to the target Acme resource."
transient_provider_outage = "Retry after Acme or the credential backend recovers."

[connector_contract]
version = 1

[[connector_contract.fixtures]]
provider = "acme"
name = "sample webhook"
kind = "webhook"
headers = { "content-type" = "application/json" }
body_json = { id = "evt-1", type = "thing.created" }
expect_type = "event"
expect_kind = "acme.thing.created"
expect_dedupe_key = "evt-1"
expect_payload_contains = { provider = "acme", event = "thing.created", id = "evt-1" }
expect_event_count = 1
```

Run:

```sh
harn package verify .
```

Use live credentials only in provider-specific integration tests. Catalog
examples and contract fixtures should run against mocked connector fixtures so
Harn CI, connector repo CI, and local authoring all stay deterministic.

## Authoring a connector

Start with [Connector authoring](./authoring.md), then add:

- a `harn.toml` package manifest with `connector_contract = "v1"`
- contract fixtures that cover normal event, ack-first response, reject, and
  poll cases where relevant
- a `README.md` with install, setup, required secrets/scopes, supported events,
  and `harn package verify` command
- mocked tests for outbound `call(...)` methods
- a small recipe example under `examples/triggers/` when the connector is
  first-party or broadly useful

The Harn-side contract is deliberately small. Keep provider SDKs or generated
API clients in separate packages when that makes the connector easier to test
and reuse, as with `notion-sdk-harn`.

---

## Read next

- [Connector parity matrix](https://harnlang.com/connectors/parity-matrix.md)
- [Connector operator runbook](https://harnlang.com/connectors/operator-runbook.md)
