feat(automations): no-code workflow automation builder (LC-495) #493
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/LC-495-workflow-automations"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
LC-495: Workflow automation builder (triggers -> actions)
No-code, room-scoped automation rules: "when X happens in this room, do Y." This is the Slack Workflow Builder core - welcome-style auto-posts and keyword auto-responders - built as a clean vertical slice over the existing event hooks and message-post pipeline.
What a room manager can build
On the room Manage page there is a new Automations card. Each rule is: a trigger (with an optional match filter) -> an action.
automationbot. The body is a template supporting{user}(triggering user),{text}(the message body) and{emoji}(the reaction).Examples: "when a message contains
help-> postNeed a hand? Ask in #support." or "when someone reacts with 🎉 -> post{user} is celebrating!".How it fits the codebase
db::automations, migration0079_room_automations.sql): a room-scoped rule table.trigger_kind/action_kindare open TEXT, not CHECK enums, so new triggers/actions are a one-file migration plus an engine branch - no table rewrite. Toggle/delete are room-scoped so a forged id from another room is a no-op.automations.rs): pure match + template helpers (unit-tested) pluson_message_posted/on_reaction_added. Hooked in off the request path (spawned, like the coyote / voice-transcription tasks) so a matched rule never slows the sender.finalize_message_send, and it ignores bot authors - so an action message cannot re-trigger automations. Bounded to 5 actions per event; per-room cap of 25 rules; action body honors the LC-153 markdown length bound.routes::automations+partials/room_automations.html): require_can_manage-gated CRUD; the shared partial is included by the manage page and rendered standalone by the handlers (the shared-partial convention). Hidden for DMs. en + es strings added (catalog parity test passes).Scope / follow-ups
v1 deliberately ships two triggers and one action as a complete slice. The ticket also lists webhook / notify / add-label actions and more triggers (member joined, etc.); those are natural follow-ons - the
*_kindcolumns and the engine's single match-set make them additive. Note: "member joined" maps poorly onto this app's open-room enclave model (public rooms have no per-room join event), so it was left out rather than half-built.Tests
just check(clippy standalone + saas + desktop + fmt),just test, andjust test-saasall pass. New:db_automations.rs(CRUD + active-trigger filter + room-scoping) and engine unit tests (filter matching, template substitution, known-kind validation).Not operator-visible: no new env var or config; no
[operator-action]marker.The runtime half: match a trigger's filter (case-insensitive keyword substring for messages, emoji match for reactions; blank = any) and run the post_message action as a lazily-created `automation` bot, with {user}/{text}/{emoji} template substitution. Bounded to 5 actions per event. No cascade/loop risk: the engine is invoked only from the human post/reaction handlers, never from finalize_message_send, and it ignores bot authors. Pure match/template helpers are unit-tested. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>