Skip to content

Configuring webhooks ​

All three source connectors deliver real-time updates through a single endpoint on your Moʻolelo deployment. This page covers what that endpoint expects, how signatures are verified, and how to manage the secrets.

The webhook URL ​

Each delivery hits:

text
https://<your-moolelo-host>/webhooks/<provider>/<instance>

Where:

  • <provider> is github, confluence, or sharepoint.
  • <instance> is the same string you used in the connector_configs row's instance column.

For example, if your deployment is at search.moolelo.example and you configured the GitHub connector with instance = 'acme', the GitHub webhook URL is:

text
https://search.moolelo.example/webhooks/github/acme

The webhook URL must be reachable from the source system's outbound IP ranges. For SaaS sources this means a public-internet HTTPS endpoint; for self-hosted sources (GitHub Enterprise Server, Confluence Data Center) it can be a private endpoint reachable from the source's network.

Signature verification ​

ProviderMechanismHeader / fieldAlgorithm
GitHubHMAC over bodyX-Hub-Signature-256: sha256=<hex>HMAC-SHA256
ConfluenceHMAC over bodyX-Hub-Signature: sha256=<hex>HMAC-SHA256
SharePoint (Microsoft Graph)Per-notification clientState matchvalue[].clientState field in bodyconstant-time string equality

Every delivery is verified on receipt. Unsigned, wrongly-signed, or missing-signature deliveries are rejected with HTTP 401.

For SharePoint specifically, the authentication model is different. Microsoft Graph doesn't HMAC-sign notifications; instead, you provide a clientState secret when creating a subscription, and Graph echoes it back inside each notification. Moʻolelo constant-time-compares the echoed clientState against the configured secret.

Secret management ​

Each provider has a single secret value the webhook receiver checks. The values are configured via environment variables on the webhook receiver service:

VariableUsed for
WEBHOOK_INGRESS_GITHUB_SECRETAll GitHub webhook deliveries
WEBHOOK_INGRESS_CONFLUENCE_SECRETAll Confluence webhook deliveries
WEBHOOK_INGRESS_SHAREPOINT_SECRETAll SharePoint subscription notifications

In Helm-deployed clusters the secrets come from a Kubernetes Secret named webhook-ingress-secrets. Operators usually wire this from HashiCorp Vault via External Secrets Operator so the values rotate without redeployment.

Because each provider has one secret across all instances, every webhook on a given provider uses the same secret. (Per-instance secrets are a future enhancement.)

The Microsoft Graph subscription handshake ​

When you create a SharePoint subscription, Microsoft Graph POSTs your webhook URL with a ?validationToken=<random> query parameter and an empty body. Your webhook URL must echo the token in the response body, in plaintext, within 10 seconds.

Moʻolelo's webhook receiver does this automatically on the POST /webhooks/sharepoint/<instance>?validationToken=... path. You don't have to do anything — but be aware:

  • Network latency on your side counts toward the 10-second budget.
  • TLS termination in front of the receiver counts.
  • If you put a CDN in front that buffers request bodies, the handshake will fail.

For internal-only (self-hosted) Microsoft Graph webhook setups, the same handshake applies; you just need internal DNS + private connectivity.

Health checks ​

The webhook receiver exposes:

  • GET /healthz — liveness; returns 200 once the process is up.
  • GET /readyz — readiness; returns 200 once the receiver is ready to accept deliveries.

Use these in your Kubernetes readiness probe and external monitoring.

Delivery retry semantics ​

Each source has its own retry policy when your webhook endpoint fails:

  • GitHub — retries 3 times with exponential backoff, then gives up. Failed deliveries are visible in the GitHub repository's webhook delivery log; you can manually redeliver from there.
  • Confluence — retries up to 5 times over ~24 hours. After that, the delivery is dropped. You can recapture missed periods by toggling the connector's mode to backfill in connector_configs.
  • Microsoft Graph (SharePoint) — retries up to 4 hours, with backoff. After that, missed notifications are gone — you're expected to resync via a delta query.

In all three cases, Moʻolelo's connector backfill mode covers any gaps without re-indexing already-known records, so a brief outage is recoverable.

Multiple instances per provider ​

If you connect two GitHub orgs (e.g., acme and acme-eu) to the same Moʻolelo deployment, the webhook URLs are distinct:

text
https://search.moolelo.example/webhooks/github/acme
https://search.moolelo.example/webhooks/github/acme-eu

But the secret is shared across instances of the same provider. If you need per-instance secrets (typically for compliance reasons), run separate webhook receivers — Helm makes this a values-file change, not a code change.

Troubleshooting ​

  • All webhooks 401. The configured secret doesn't match what the source has. Re-paste the secret on the source side; for GitHub, the per-repository secret is independent of any other repository's.
  • All webhooks 501. The provider isn't enabled on the receiver. Check WEBHOOK_INGRESS_PROVIDERS includes the provider name.
  • GitHub webhook delivery delayed by minutes. GitHub webhooks are at-least-once and best-effort; large repositories can occasionally take a few minutes during incidents on GitHub's side. Your connector backfill catches up if a delivery is dropped entirely.
  • SharePoint subscription expires. Drive-item subscriptions max out at ~60 minutes per Microsoft Graph's policy. You need an operator-side scheduler that calls PATCH /subscriptions/<id> to renew. This isn't something Moʻolelo handles automatically today.

Moʻolelo — self-hosted federated enterprise knowledge platform.