Redesign messaging adapter base with caller-resolves pattern
What does this MR do and why?
Redesigns the messaging adapter base class (Ai::Messaging::Adapters::Base) to provide a clean foundation for triggering AI flows from any messaging surface (Slack, GitLab note mentions, @GitLabDuo, future surfaces).
This replaces the approach in !234959 (closed) (which is being closed without merge) based on architectural feedback from that review. The three biggest changes:
-
Adapters::Base#triggerbecomes the single orchestration primitive. The concrete adapter (surface) owns all policy decisions — authorization, service account selection, flow selection, project selection — by implementingbuild_trigger_bundle. The sharedBase#triggerhandles only the mechanical work no surface should do for itself: composite identity linking, SA project membership, callback context enrichment, resource translation, and workflow execution. This eliminates the "two parallel orchestration paths" problem whereRunServiceandTriggerFlowServiceboth ended up atExecuteWorkflowServicebut resolved and gated completely differently. -
TriggerBundlevalue object replaces symbol-keyed hashes. AData.define-based struct with required-field validation catches contract violations at construction time inside the adapter, instead of with a deepNoMethodErrorinsideExecuteWorkflowService. The surface says: "Run this flow definition using this service account, in this project, against this resource" — and the type system enforces that contract. -
Tiered resilience replaces blanket
safe {}.on_request_received(the user's acknowledgement) is wrapped inmust {}which short-circuits on failure. Best-effort hooks likeon_flow_startedusesafe {}. Security-critical steps (composite identity, SA membership, workflow execution) have no wrapper — they fail loudly. This fixes the silent-failure problem where a failed acknowledgement note would let the flow proceed, leaving the user with no visible response.
Additional changes:
TriggerFlowServicedeleted. Its namespace resolution, enablement check, and workspace project logic will be absorbed by concrete adapters'build_trigger_bundleimplementations (out of scope for this MR).CallbackWorkeruses descendants-based registry. Adapters declareself.adapter_key; the registry is built fromBase.descendantsinstead of a hardcoded hash.enriched_callback_contextauto-injects the adapter key so adapters cannot accidentally write a mismatched string.- Single
on_flow_failedhook withworkflow:kwarg replaces the dualon_flow_failed/on_trigger_failedhooks. Sync failures passworkflow: nil; async failures pass the workflow object. Adapters branch onworkflow.present?for conditional cleanup (e.g. Slack only removes the👀 reaction when the workflow existed). - Composite identity linking uses
Gitlab::Auth::Identity.link_from_web_requestdirectly, per the review feedback on !234959 (closed) (!234959 (comment 3328524508)). No new auth-domain methods or parallel modules.
What this MR does NOT do
- Does not add concrete adapters (Slack, GitlabNote) — those are separate MRs that stack on this.
- Does not change
ExecuteWorkflowService's public interface. - Does not refactor
RunService— that remains a parallel path for non-adapter surfaces until a future consolidation. - Does not add a feature flag — the messaging adapter is not used in production yet.
References
- Design issue: #599691 (closed)
- Closes !234959 (closed) (superseded by this redesign)
- Epic: #590434
- Architectural discussion: #599330 (closed)
- Review concern that motivated auth-domain alignment:
!234959 (comment 3328524508) - Flow versioning (parallel work): !235204 (merged)
How to set up and validate locally
This MR changes infrastructure that is not yet called from production code paths. Existing flows (RunService path) are untouched. Validation is via specs:
bundle exec rspec \
ee/spec/services/ai/messaging/adapters/base_spec.rb \
ee/spec/workers/ai/messaging/callback_worker_spec.rbNo changelog needed — internal infrastructure not yet used in production.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.