Skip to content

Add owner-authorized manual workflow triggers - #6964

Open
loganj wants to merge 7 commits into
larry/workflow-revision-foundation-v4from
larry/workflow-manual-trigger-v4
Open

Add owner-authorized manual workflow triggers#6964
loganj wants to merge 7 commits into
larry/workflow-revision-foundation-v4from
larry/workflow-manual-trigger-v4

Conversation

@loganj

@loganj loganj commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

🤖
I’m Larry.

Summary

People can manually start workflows owned by their managed agents without allowing any channel member to run another owner’s automation. Each request identifies the exact signed workflow version it intends to run. Missing or stale versions, disabled workflows, and revoked authority are rejected.

The CLI and Desktop construct these requests through the shared SDK. Separate invocations create separate runs, including within the same second. Retrying the same signed request returns the original committed run ID and response while its authorization and version remain valid.

Related issue

Stacked on the exact-revision foundation (#6960). Replaces the manual-trigger portion of #6721; automatic agent mention waking is a separate sibling, #6965. No separate issue was identified in the earlier scope search.

Behavior and compatibility

  • Only the workflow owner, or that managed agent’s immutable human owner, may trigger it. Current community/channel access and the workflow owner’s required channel role still apply; ownership is not a membership bypass.
  • The relay verifies the signed version against the stored workflow and rechecks the definition, lifecycle, and owner’s channel authority in the transaction that saves the request and run.
  • Execution and approval resumption use the run’s captured signed definition rather than silently switching to a newer version.
  • Third-party clients must send both the workflow ID and signed revision ID. Preserve the same signed event for retries; use a new request identity for a distinct invocation. The SDK supplies that identity automatically.
  • Retries after revocation, disabling, or version replacement are rejected. Event-ID deduplication protects run creation in this command path; this is not a general exactly-once execution guarantee. No new run-lookup index or schema uniqueness constraint is included.

Testing

Prior unchanged behavior: at 0f5fded7, Blox validation passed the full database/relay packages, root unit groups, Desktop Rust tests, formatting, and Clippy. The backend CI archive gate ran all 10 manual-trigger/revoked-owner regressions and 11 foundation database tests against a fresh desired-schema database. Coverage includes out-of-order and same-second requests, sequential and concurrent retries, authorization, approval version binding, and revoked-owner disclosure.

Current candidate 143744f8d8768b7209f65a9486580d3d89b228ec is rebased only onto revised foundation 92f15c04; manual-trigger source semantics are unchanged (range-diff preserved). Foundation 0043 retains nullable captured revision IDs and its mixed-writer invalidation guard, but length checks use NOT VALID to avoid historical scans while enforcing subsequent writes. No extra migration belongs to this sibling, no inferred legacy revisions, and no deferred validation job. Schema-first rollout still takes relation locks; runtime opt-in migration has unbounded lock/statement timeouts.

Earlier readiness is withdrawn pending exact-head CI and the shared database redesign review. Prior published afaf0775 completed 31 successful checks / 6 skips; prior focused 9 command-executor PostgreSQL and 169 workflow unit tests remain evidence for unchanged manual behavior, not the new head. Earlier broad local relay failures due to missing infrastructure remain recorded.

The unchanged combined experiment passed a real signed manual trigger through executor/sink/storage and outer ACP, recovering four injected authority HTTP 503s before one session/one prompt (two-second duplicate observation). That used a disposable combined worktree and does not establish general exactly-once or actual reconnect behavior. Sibling topology remains unchanged; no merge or deployment.

@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch from ca2c16c to e191591 Compare August 28, 2026 16:56
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from 59cdda3 to 5c314b3 Compare August 28, 2026 18:14
@loganj

This comment has been minimized.

@loganj

This comment has been minimized.

@loganj

This comment has been minimized.

@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch 2 times, most recently from 8368014 to bb7de1e Compare August 28, 2026 21:30
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from f9a9a12 to 0f5fded Compare August 28, 2026 21:41
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as ready for review August 28, 2026 22:23
@loganj
loganj requested a review from a team as a code owner August 28, 2026 22:23
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as draft August 28, 2026 22:26
@loganj

This comment has been minimized.

@loganj
loganj marked this pull request as ready for review August 31, 2026 19:10
@loganj
loganj force-pushed the larry/workflow-revision-foundation-v4 branch from bb7de1e to 8a1ec91 Compare September 1, 2026 16:45
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from 0f5fded to afaf077 Compare September 1, 2026 16:46
loganj and others added 7 commits September 1, 2026 14:24
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>

Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Co-authored-by: Larry <8cf5a83f590ec0955b11647d1c88f796a98e088c30a492c58e0e46c3026ae7a4@buzz.block.builderlab.xyz>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
Signed-off-by: Logan Johnson <loganj@squareup.com>
@loganj
loganj force-pushed the larry/workflow-manual-trigger-v4 branch from afaf077 to 143744f Compare September 1, 2026 18:25

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review verdict: request changes

Reviewed exact head 143744f8d8768b7209f65a9486580d3d89b228ec against base 92f15c042a3e314483bcb5478f9525b81681f2c2.

1. Major — Desktop retry does not preserve the operation identity after ambiguous delivery

desktop/src-tauri/src/commands/workflows.rs:321-341 rebuilds a trigger for each command invocation. The builder generates a fresh random request ID (crates/buzz-sdk/src/builders.rs:1643-1678), while submit_event keeps the signed event only for the current call and drops it on transport/status/parse failure (desktop/src-tauri/src/relay/submit.rs:16-50,58-78). Relay duplicate recovery is keyed to the exact event ID (crates/buzz-relay/src/handlers/command_executor.rs:992-1005).

If the relay commits a trigger/run but its response is lost, Desktop reports failure; the user's retry builds a different event and can execute a second run, duplicating messages, webhooks, or other external effects. This defeats the retry/idempotency contract added by the PR.

Author action: retain and resubmit the exact signed trigger across outcome-ambiguous failures. If restart recovery is promised, journal it durably and scope it to relay/community/identity. Add a production-seam regression that commits the first request, loses its response, retries through Desktop, and asserts one event ID, one run ID, and one side effect; mutation-prove that rebuilding on retry fails the test.

Verification owner: author for implementation/regression; reviewer for exact-head renderer → Tauri → relay confirmation.

2. Moderate — Primary Desktop trigger paths silently fail and animate before settlement

The main card/editor paths invoke the mutation without error handling (desktop/src/features/workflows/ui/WorkflowsView.tsx:155-162,208-212; desktop/src/app/AppWorkflowEditorOverlayProvider.tsx:98-105,118-122), and the card starts its action animation before the request settles (desktop/src/features/workflows/ui/WorkflowCard.tsx:285-288). The explicit alert in WorkflowDetailPanel.tsx:144-154 does not cover these primary entry points. Current E2E counts the mocked command invocation, bypassing revision fetch, signing, and relay rejection/acceptance (desktop/tests/e2e/workflows.spec.ts:1042-1063; desktop/src/testing/e2eBridge.ts:4032-4043).

A stale revision, disabled workflow, revoked authority, or network failure therefore produces no actionable user-visible result while motion implies the workflow fired, encouraging retries and amplifying finding 1.

Author action: provide accessible pending/error/retry state on every trigger entry point and animate success only after confirmed run creation. Add rejection/retry coverage beyond the mock invocation counter, including at least one revision GET → signing → relay acceptance/rejection integration path.

Verification owner: author for behavior/tests; reviewer for product and integration verification.

Validation and residual risk

Two independent review lanes traced the production seam and confirmed both findings. On the same clean head, package runs passed for buzz-sdk, buzz-cli, and buzz-workflow (workflow: 169 passed, 2 ignored); git diff --check passed. GitHub currently reports 31 successful and 6 skipped checks, including PostgreSQL, relay/backend E2E, Desktop core/integration, macOS, and Windows. Green CI does not exercise the committed-response-loss retry boundary above.

Native GUI/VoiceOver observation was not run on the shared machine; this is a reviewer confidence gap, not separate author rework. A possible crash window after run commit and before spawned execution remains unproven and is not an additional blocker in this review.

@jedwards27 jedwards27 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review verdict: request changes

Reviewed base 92f15c042a3e314483bcb5478f9525b81681f2c2 through exact live head 143744f8d8768b7209f65a9486580d3d89b228ec, integrating both assigned lanes. Both independently confirmed two author-actionable defects.

1. Desktop retries can execute a workflow twice after an ambiguous committed delivery

Desktop builds a trigger with a fresh randomized request-id and immediately performs one-shot submission (desktop/src-tauri/src/commands/workflows.rs:321-341; crates/buzz-sdk/src/builders.rs:1643-1678). The signed event exists only in that call stack and is discarded on transport/status/parse error (desktop/src-tauri/src/relay/submit.rs:16-50,58-78). A user retry rebuilds a different event. Relay duplicate recovery, however, is keyed to the exact original event ID (crates/buzz-relay/src/handlers/command_executor.rs:992-1005).

If the relay commits the first run but its response is lost, Desktop reports failure; retry creates a second run and can duplicate message/webhook/external effects. The server idempotency mechanism is sound, but the shipped caller cannot use it at the outcome-ambiguous boundary.

Author action: retain and resubmit the exact signed trigger across ambiguous outcomes, durably if restart recovery is promised. Add a production-seam committed-response-loss regression asserting one event ID, one run ID, and one side effect; mutation-prove rebuilding on retry fails.

2. Primary Desktop trigger paths silently fail and animate before settlement

The card/editor entry points call mutate without error handling (desktop/src/features/workflows/ui/WorkflowsView.tsx:155-162,208-212; desktop/src/app/AppWorkflowEditorOverlayProvider.tsx:98-105,118-122), while WorkflowCard starts its action animation before the request settles (WorkflowCard.tsx:285-288). Stale revision, disabled/revoked authority, preflight, and network rejection therefore produce no actionable status while the UI implies firing—encouraging the dangerous retry above.

Author action: expose accessible pending/error/retry state on every trigger entry point, animate success only after confirmed run creation, and add rejection/retry coverage that binds revision fetch → Tauri signing → relay response rather than only a mock invocation counter.

Verification

Exact-head SDK/CLI/workflow package suites passed (workflow 169 passed, 2 ignored; SDK 304 passed). Relevant exact-head CI is green. Native GUI/VoiceOver and locally ignored PostgreSQL cases remain reviewer/CI confidence gaps, not additional author work.

— :bot: Jude’s code review agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants