Route multi-step routines onto Interchange's native workflow trigger - #256
Merged
Merged
Conversation
Covers triggerNativeWorkflowRoutineRun (fires a signed mail at a definition's live deployment, fails loud when none exists or the deployment is unrouteable) and the routine launcher's routing: a multi-step definition goes through the native trigger instead of the folded launcher, while single-step routines are unaffected. Also rewrites routine-launchability.test.ts, which previously asserted every default workflow must be single-step — the exact restriction this change removes.
…ow trigger Routines could only launch through @corbits/folded-runs, whose readFoldedBody has always required exactly one step -- a multi-step definition threw MultiStepFoldUnsupportedError synchronously, which surfaced as a bare 500 on the first launch attempt. A multi-step definition can only exist in this repo as a code-sourced @intx/workflow package deployed through POST /workflows/deployments, so a live, self-anchored deployment already exists for it. The routine launcher now catches MultiStepFoldUnsupportedError and fires that deployment directly with a signed mail message via SidecarRouter's public routeMail -- the same native primitive the dedicated POST /workflows/:id/mail route uses, assembled from the same public @intx/mime/@intx/crypto primitives since that route's own trigger function isn't exported. Single-step, hand-authored definitions are unchanged: they have no source of their own and still need launchFoldedRun's render-and-deploy bridge, so this is a deliberate split by definition shape, not two competing launchers for one case. Also wires @intx/hub-api's createMailTriggeredRunGrantsMaterializer into the hub's sidecar lookups. Without it, a plain mail delivered to a workflow deployment's address (as this new path does) would reach the sidecar without its run's grants ever being materialized, leaving it authorized for nothing. This was previously unwired -- only the dedicated HTTP trigger route staged a run's grants inline -- so this closes a real gap for any native mail-triggered run, not just routines. GET /routines/:id/runs already reads status generically off workflow_run by id, so a native run's status/completion is observable there with no further wiring: the returned run id is the deployment's own anchor, the same coarse per-deployment handle POST /workflows/:id/mail itself returns synchronously.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
@corbits/folded-runs, whosereadFoldedBodyhas always required exactly one step (MultiStepFoldUnsupportedError) — a multi-step definition threw synchronously on the very first launch attempt.@intx/workflowpackage deployed viaPOST /workflows/deployments, so a live, self-anchored deployment already exists for it by construction. The routine launcher now catchesMultiStepFoldUnsupportedErrorand fires that deployment directly with a signed mail message throughSidecarRouter.routeMail(a public method already in everyFoldedRunsDepscaller's hands) — the same native primitivePOST /workflows/:id/mailuses, assembled from the same public@intx/mime/@intx/cryptoprimitives since that route's own trigger function isn't exported from@intx/hub-api.@intx/hub-api's exportedcreateMailTriggeredRunGrantsMaterializerinto the hub's sidecar lookups (apps/hub/src/index.ts). This wasn't wired before — only the dedicated HTTP trigger route staged a run's grants inline — so a plain mail delivered to a workflow deployment (as this new path does) would otherwise reach the sidecar without its run's grants ever being materialized. This closes a real gap for any native mail-triggered run, not only routines.packages/hub-client/test/routine-launchability.test.ts, which asserted everyDEFAULT_WORKFLOWSentry must be single-step — the exact restriction this PR removes. It now asserts structural well-formedness (stepOrder/steps agree) instead.Design notes
launchFoldedRun's render-and-deploy bridge (itself a call into Interchange's realdeployAdoptedWorkflowFromSource, not a reimplementation). This is a deliberate split by definition shape (does the definition already have real deployed source, or does one need to be rendered for it), not two launchers competing for the same case.GET /routines/:id/runs'sresolveRunSummaryalready reads status generically offworkflow_runby id, so a native run's status is observable with zero further wiring. The caveat: the returned run id is the deployment's own anchor — the same coarse, deployment-level handlePOST /workflows/:id/mailitself returns synchronously (its true per-fire child run id is minted by the supervisor and isn't known until its ownRunStartedevent lands). A routine that fires the same shared deployment repeatedly will show that one anchor id/status rather than a distinct row per fire; resolving the precise per-fire child run (pollGET /workflows/:id/runsfor a new id, proven pattern inscripts/e2e/cl-6324-launch-proof.ts) is a follow-up, not done here.scripts/e2e/cl-6324-launch-proof.ts. Nothing in this change touches that mechanism — the job here was only making an already-working native execution reachable from a routine at all.createMailTriggeredRunGrantsMaterializerfrom@intx/hub-api,SidecarRouter.routeMail/sendRunGrantsfrom@intx/hub-sessions, plus public@intx/mime/@intx/crypto/@intx/typesprimitives). Nothing undervendor/intx/was modified.workflows/last-30-days-researchfolded to one step (CL-6495) — restoring its original six-step content is a content change, out of scope for this launch-path fix, now that multi-step CAN launch.Test plan
apps/hubfull suite: 153 pass / 0 fail (includes 12 pre-existing routine-launcher tests, unchanged — proves single-step regression protection)native-workflow-routine-launch.test.ts— fires a signed mail at a live deployment and returns its anchor id; fails loud (named error) when no live deployment exists or the only one is terminal; fails loud (not silently) when the deployment is unrouteablepackages/hub-clientfull suite: 162 pass / 0 failbunx tsc --noEmitclean onapps/hubandpackages/hub-clientscripts/e2e/cl-6324-launch-proof.ts