Integrations architecture
Every integration Landfall ships — AWS, Datadog, Coralogix, PagerDuty, GitHub, and whatever comes after — is built on one shared model, not a parallel one-off per provider. This page describes that model once; each integration's own setup guide links back here for the shared parts, using GitHub as the worked example throughout.
Why this is one page, not one per integration
A connected system the investigator agent can't dynamically see, or that can't itself raise an incident, is a second-class integration — it undermines both the "agent crew investigates in the conversation" premise and the "any signal can start a war room" premise the platform is built on. So every integration is held to the same four requirements: a documented setup guide with real screenshots, automatic agent access with no per-provider code, the ability to open an incident, and — this page — one current, shared description of how all of that actually works, updated as integrations are added rather than forked into a new document each time.
The connector framework
Every provider — a telemetry source, a cloud account, a comms/paging provider, a source-control provider — implements the same small contract:
- IntegrationAdapter — declares the provider's id, its config schema (which fields are secret, which aren't), and a verify() that checks a set of credentials actually authenticate before anything is saved. A credential that can't authenticate is refused, not silently stored as "configured."
- ConfigStore — the durable, per-tenant, RLS-protected record of what's connected: non-secret fields (org login, installation id, account id) live in Postgres; secret values live in a separate secrets backend and are never returned to any client, ever.
- SecretsBackend — AWS Secrets Manager in every real environment (LocalStack locally/in CI). Most providers store a per-tenant secret here. GitHub is the one structural exception: see below.
Adding a provider means implementing this contract, not inventing a new connection model. GitHub's adapter is the same shape as AWS's or Datadog's; only what it stores and how it authenticates differ.
GitHub's shape: one platform App, not a per-tenant secret
Most providers ask each tenant for their own API key or role — an independent secret per organization. A GitHub App works differently by GitHub's own design: Landfall registers one App at the platform level (an App id and a private key), and each organization installs that App, choosing which repositories it can see. Landfall's ConfigStore row for a GitHub connection holds only two non-secret, tenant-identifying fields — the org login and the installation id — never a credential. At call time, a platform-level component signs a JWT with the App's private key, exchanges it for a short-lived (about one hour) access token scoped to that one installation, and caches it in memory until shortly before it expires. No installation token is ever persisted; a process restart just means the next call re-mints one.
This is why GitHub's setup guide has no "paste your API key here" step — see Connecting GitHub.
Dynamic agent access — no per-provider agent code
The investigator agent doesn't have a hardcoded list of "sources it knows about." It reads one thing: ctx.scope.capabilities, built fresh for every investigation from the tenant's actually-configured connections. The moment a connection exists — GitHub or otherwise — three things happen automatically, with zero source-specific agent code:
- It's listed by the signals service's plugin catalog for that tenant, alongside every other connected source.
- It's folded into ctx.scope.capabilities, carrying its real operation descriptors — for GitHub, that's search/read-file/list-commits/diff/ blame/correlate-deploy, each with its own parameter shape.
- It's given a generic {source}/query scope-resource key by the same widening step every connected, non-canonical source goes through — GitHub gets no special case here at all.
In plain terms: connecting GitHub doesn't require shipping a new agent tool or a new prompt. The agent's existing generic query mechanism just gains a new source to query, exactly the way it gained AWS, Datadog, or Coralogix — a genuinely new integration widens what the agent can reach without widening the agent's own code.
The incident-triggering model
A source that can only be queried during an investigation is half an integration — the platform's other premise is that any signal can open the investigation in the first place. Every trigger source, GitHub included, goes through the same pipeline (libs/triggers):
- Signature verification first. A dedicated guard checks the delivery's signature before anything else runs — an unverified delivery never reaches parsing, let alone incident creation.
- Uniform rejection. A bad signature and a signature that's valid but names a tenant that isn't actually connected get the identical refusal from the outside. The distinct reason is recorded only in an internal audit trail — never in the response — so the endpoint can't be used to enumerate which organizations are connected.
- Normalize → resolve entity/severity. The provider-specific payload becomes the same shared trigger shape every source produces, with severity derived from that provider's own native severity field where one exists.
- externalRef dedup. Before creating an incident, the delivery's own identifier (a GitHub delivery id and alert/run id, a PagerDuty incident id, …) is checked against existing incidents. A match means "already handled" — accepted and ignored, never a second incident. This is the same mechanism PagerDuty and Opsgenie already use, not a new one built for GitHub.
See Triggering Integrations → GitHub for the event types GitHub routes through this pipeline, and how the deploy-critical-workflow opt-in keeps a flaky CI run from opening a war room on its own.
Read-only is enforced at the credential, not by convention
For every integration on this platform, "the agent only reads" is not a prompt instruction — it's a property of the credential itself. GitHub's App has no write scope at all in its registration; there is no code path capable of issuing a write call, because the token GitHub issues literally cannot perform one. The same bar applies across every provider: the credential can't write, so there's nothing relying on application-layer discipline alone to keep it that way.
In one sentence, per integration
| Integration | Credential shape | Can trigger? |
|---|---|---|
| AWS | Per-tenant IAM role (no keys) | Yes — CloudWatch alarm → SNS → webhook |
| Datadog | Per-tenant API + application key | Yes — monitor alert webhook |
| Coralogix | Per-tenant API key | Yes — alert webhook |
| PagerDuty | Per-tenant read-only API key + webhook | Yes — incident.triggered/escalated/resolved |
| GitHub | One platform App; per-tenant installation id only | Yes — security alerts + deploy-critical workflow failures |