picatz / picatz/flowstate

Design: trigger types — every way a run begins, one contract, armed never automatic

Open
#159 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

design dsl kind/design-record
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

  1. 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 way flow run --input is. The trigger is a source of arguments, never a source of behaviour.
  2. 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 (generalizing flow schedule create) arms it, under the caller's identity and tenancy.
  3. 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.