Trigger event schema
TriggerEvent is the normalized envelope every inbound trigger provider
converges on before dispatch. Connectors preserve provider-specific payload
fidelity inside provider_payload, but the orchestration layer always sees the
same outer shape:
import "std/triggers"
fn on_event(event: TriggerEvent) {
let payload = event.provider_payload
if payload.provider == "github" && payload.event == "issues" {
log(payload.issue.title ?? "unknown")
}
let signature = event.signature_status
if signature.state == "failed" {
log(signature.reason)
}
}
Envelope fields
TriggerEvent carries:
id: runtime-assigned event id.provider: provider identity such as"github","slack","cron", or"webhook".kind: provider-specific event kind.received_at: RFC3339 timestamp captured by the runtime.occurred_at: provider-reported RFC3339 timestamp when available.dedupe_key: delivery id or equivalent idempotency key.trace_id: trace correlation id propagated through dispatch.tenant_id: optional orchestrator-assigned tenant namespace.headers: redacted provider headers retained for audit/debugging.provider_payload: provider-tagged payload union.signature_status: typed verification result.
Signature status
signature_status is a discriminated union:
{ state: "verified" }{ state: "unsigned" }{ state: "failed", reason: string }
Unsigned events are valid for synthetic sources such as cron. Failed events can still be logged for audit purposes even if the dispatcher rejects them.
Provider payloads
The initial std/triggers payload aliases are intentionally small. Each
provider variant exposes a stable normalized surface plus raw: dict. GitHub's
payload is narrowed into thirteen event families covering the
harn-github-connector
v0.2.0 webhook contract — issues, pull_request, issue_comment,
pull_request_review, push, workflow_run, deployment_status,
check_run, check_suite, status, merge_group, installation,
and installation_repositories — with event-specific top-level fields
such as issue, pull_request, comment, review, commits,
workflow_run, check_suite_id, merge_group_id,
repositories_removed, plus the connector-promoted topic,
repository, and repo shared across every variant. Slack's
payload is narrowed into Message (message.*), AppMention,
ReactionAdded, AppHomeOpened, and AssistantThreadStarted. Notion's
payload is narrowed around the current connector landing:
subscription.verification, page.content_updated, page.locked,
comment.created, data_source.schema_updated, plus polled fallback events
surfaced through payload.polled. All providers still preserve the full outer
envelope in raw:
GitHubEventPayloadSlackEventPayloadLinearEventPayloadNotionEventPayloadCronEventPayloadGenericWebhookPayloadA2aPushPayloadExtensionProviderPayload
The runtime registers these through a ProviderCatalog, so future connectors
can contribute new payload schemas without rewriting the top-level
TriggerEvent envelope.
Header redaction
The runtime keeps delivery, event, timestamp, request-id, signature, and
user-agent headers by default. It redacts sensitive headers such as
Authorization, Cookie, and names containing secret, token, or key
unless they are explicitly allow-listed as safe metadata.