Skip to main content

StoryTrigger

StoryTrigger is the durable admission object for external trigger delivery. Impulses and other trusted SDK clients submit StoryTrigger requests; the controller validates the request, creates or reuses the target StoryRun, and records the durable decision in status.

If the accepted trigger payload is larger than storyrun.max-inline-inputs-size, the controller offloads the resulting StoryRun.spec.inputs to shared storage before creating the run. Large trigger-driven workflows therefore still require Bobrapet shared storage (controller.storage.*) even when the trigger request itself is accepted.

Why it exists

Before StoryTrigger, the SDK created StoryRun objects directly from trigger helpers. That made ambiguous create failures hard to reason about and pushed too much trigger-idempotency logic into the client.

StoryTrigger moves the durable boundary earlier:

  1. client submits a durable request
  2. controller decides Created, Reused, or Rejected
  3. client reads back the resolved StoryRun

Shape

apiVersion: runs.bubustack.io/v1alpha1
kind: StoryTrigger
metadata:
name: github-pr-review-trigger-b9876960c1879825
namespace: github-pr-review
spec:
storyRef:
name: pr-review-assistant
deliveryIdentity:
mode: token
key: github:pull_request:37
inputHash: 4f530b2d9b7fce9bc9f0dd0f7fd0d7f47b4f0ab6d7bcf9c5880aa9d75ab0d9b6
submissionId: github:pull_request:37
inputs:
event: pull_request
action: opened
status:
decision: Created
storyRunRef:
name: pr-review-assistant-abc123

Key fields

FieldMeaning
spec.storyRefTarget Story to execute.
spec.deliveryIdentity.modenone, token, or key.
spec.deliveryIdentity.keyStable business identity when dedupe is required.
spec.deliveryIdentity.inputHashCanonical input hash paired with the business key.
spec.deliveryIdentity.submissionIdLogical submission-chain identifier reused across retries.
status.decisionController-owned durable result: Pending, Created, Reused, or Rejected.
status.storyRunRefResolved StoryRun once the request completes.

Naming rule

metadata.name is deterministic. It is derived from:

  • story namespace
  • story name
  • deliveryIdentity.key when present
  • otherwise deliveryIdentity.submissionId

This allows retries to find the same durable request instead of creating multiple admission objects.

Decision meanings

DecisionMeaning
PendingController has not finished resolving the request yet.
CreatedController created a new StoryRun.
ReusedA matching existing StoryRun was found and reused.
RejectedThe request identity conflicted or failed validation.

SDK behavior

The Go SDK trigger helpers submit StoryTrigger and wait for resolution:

ctx = sdk.WithTriggerToken(ctx, "github:pull_request:37")
run, err := sdk.StartStory(ctx, "pr-review-assistant", inputs)

The helper still returns a StoryRun, but the durable admission authority is the StoryTrigger.

Client RBAC

Trusted clients that submit StoryTrigger requests need:

  • storytriggers create,get
  • storyruns get

If the same client also stops active stories through the SDK, it additionally needs:

  • storyruns/status patch

Managed Impulse runner identities should cover this baseline automatically. Custom ServiceAccounts must bind these permissions explicitly. See Managed Runner RBAC.

Debugging

kubectl get storytrigger -n <namespace>
kubectl get storytrigger <name> -n <namespace> -o yaml
kubectl get storyrun <name> -n <namespace> -o yaml

Look at:

  • status.decision
  • status.reason
  • status.message
  • status.storyRunRef