Relationships
#3094 Deliver workflow signals through swamp serve
Opened by hammz · 10/6/2026
Problem
swamp-club#3093 delivers a signal by creating a write-once outcome record, but only the CLI can signal, and only on a machine with the repository and its datastore. An outside system cannot call in: there is no server form of workflow signal or workflow waits, and no access action a callback identity could be granted.
This issue is the first of four steps. It covers delivery and authority only. Resume stays manual after it; a signalled run is resumed with the existing workflow resume, locally or through serve.
Proposal
- One acceptance use case in libswamp (
workflowSignalinsrc/libswamp/workflows/signal.ts), exposed through the CLI, a WebSocketworkflow.signalrequest and an authenticated HTTP POST. - A server form of the waits listing, and
--serverforms ofswamp workflow signalandswamp workflow waits. - A new
signalaction besiderun,read,write,approveandadmin. It allows delivering to a wait on a workflow and nothing else. Proposed: arungrant impliessignal, as it impliesapprove, and asignal-only grant suits a callback identity. - A signal names a wait ID and nothing else, so the workflow to authorize against is known only from the wait's registration. An unknown wait ID and an unauthorized caller get the same answer, so a response does not reveal whether a run exists.
- Refusals sent to a caller who cannot read the workflow do not name its workflow, run or step, and do not carry an earlier signal's receipt.
- Receipt metadata is written by the server:
submittedByis the authenticated principal, never a value from the request. The submitter is an audit actor and is never the identity that executes downstream steps. - Logs and audit events record receipt IDs and outcomes, never the payload.
- The waits listing shows a caller only the waits of workflows they may read or signal.
Open decisions
- Does a
rungrant implysignal? Proposed yes, with a serve flag to require an explicit grant, asrunImpliesApprovehas. - Whether a
signal-only grant may list waits, or only deliver to a wait ID it was given.
Acceptance criteria
- A caller holding only a
signalgrant can deliver a signal over HTTP and over WebSocket, and cannot start, approve, resume or read a run with it. - An unknown wait ID and a wait the caller may not signal are answered identically.
- A signal delivered through serve is applied by the next resume exactly as one delivered by the CLI.
- All serve instances on a datastore must be upgraded before a workflow with a wait is run; an older instance refuses such a run rather than mishandling it (already the case since swamp-club#3093).
Tests
- Access tests for the
signalaction and for the indistinguishable unknown and unauthorized answers. - Handler tests for payload refusal, an already settled wait and an expired wait over both transports.
- CLI and HTTP journeys in swamp-uat.
Follow-ups
- swamp-club#3108: resume signalled runs automatically (continuation claim and sweep).
- swamp-club#3109: settle expired waits from serve, and a serve-configured maximum timeout.
- swamp-club#3110: show signal waits to remote clients and the dashboard.
Out of scope
Everything in the follow-ups, plus provider webhooks that resolve a wait, reserving a wait before a request step, capability links, schema-generated forms, wait_until polling, and leases with fencing for executors.
Depends on
swamp-club#3093 (write-once outcome records), merged.
References
The Wait for Signal section of design/primitives/workflows.md, including Mixing builds and Limits of this version.
In Progress
Click a lifecycle step above to view its details.
Sign in to post a ripple.