Design: trigger types — every way a run begins, one contract, armed never automatic
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
Schedules (#139) established the pattern; this design extends it to every other way a run can begin, and says how triggers, typed inputs, and dispatch: (#157) compose into one entry-point story.
The contract, learned from schedules and kept
- A trigger's product is a run with typed, validated inputs. Whatever the source — a cron firing, a verified webhook, a queue message, a forge event — what crosses into the run is a binding against the workflow's declared
inputs:, checked the same wayflow run --inputis. The trigger is a source of arguments, never a source of behaviour. - The declaration starts nothing; an operator arms it. #139's rule, stated for cron and true for everything: a file that begins running on merge is a surprise, and a webhook that goes live because a YAML key appeared is a security incident.
triggers:declares what the workflow is prepared to be started by;flow trigger create(generalizingflow schedule create) arms it, under the caller's identity and tenancy. - Trigger vs signal stays a strict vocabulary line. A trigger starts a run; a signal reaches a running one. Webhooks (#96) bridge to both, but the words never blur — one concept, one name.
The types, in order of demand
| Type | Source | Notes |
|---|---|---|
schedule |
cron/interval | shipped (#139) |
webhook |
verified HTTP delivery | #96's design: verification first-class (HMAC/signature per provider), payload → inputs through a declared mapping, never raw request into scope |
event (forge) |
PR opened, push, release | rides the forge plugins (#149) + webhook machinery; the GHA pull_request_target conflation is the anti-pattern — which credentials a run gets is policy at arm time, never implied by event type |
message |
queue/stream (SQS, Pub/Sub, NATS) | plugin-provided source |
object |
bucket/file events | plugin-provided source |
api / manual |
flow run, MCP |
already exists; named so the table is total |
Extensibility: trigger sources as a plugin capability
A CAPABILITY_TRIGGERS plugin watches its source and starts runs through the front door — the same Run RPC, same identity, same tenancy, same validation — never a privileged side channel. The plugin holds the watching; the engine holds the admitting. This keeps every entry point inside the one policy surface, and makes a new trigger type (a Kafka topic, a calendar, an IMAP inbox) a plugin someone ships rather than an engine release. Remote trigger plugins inherit #151 whole.
How it composes with dispatch:
One workflow, many event kinds, no N-copies:
triggers:
webhook: { events: [issue_comment, pull_request] }
inputs:
event: { type: object }
steps:
- id: route
dispatch:
on: ${inputs.event.kind}
cases:
issue_comment: { steps: [ … ] }
pull_request: { steps: [ … ] }
The trigger delivers typed data; dispatch: routes on it among compile-time-known branches. The pair is the whole "event-driven application" story with zero new determinism surface — which is why #157's dispatch node and this design should land aware of each other.
Refusals carried forward
No trigger auto-arms from the file. No raw payload enters scope unverified or unmapped. No trigger type implies a credential grant (the pull_request_target lesson). No second spelling of "arguments" — a trigger binds inputs:, the same inputs: everything else binds.
Related: #96 (webhooks — this issue's webhook row is its design slot), #139 (the pattern), #157 (dispatch:), #149/#151 (plugin-provided sources, remote), #153 (a triggered run must be as debuggable as a manual one).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the schedule pattern in #139, then inspect the existing flow run and flow schedule create entry points and the Run RPC. No files or tests are named; the design is done when trigger sources, arming, typed input validation, plugin admission, and dispatch: composition have an agreed implementation path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, backend, devops
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100