Adds durable, identity-neutral, workflow-bound human tasks, and reconciles the REST surface with the approved Studio contract. - Flat summary/detail DTOs, a global capability descriptor, and workflow context captured at activation. - Scope is part of the list authorization predicate; manager decisions require manage:user-tasks; a denied command answers 404 so it cannot prove a task exists. - Guest sessions are task-scoped, action-allowlisted, and revoked when the task closes. Invitations resolve by token hash through the repository, wait in a Data Protection encrypted outbox, and are rate limited per caller. - Masked form values are disclosed only through an audited reveal command. - Store-specific concurrency failures are translated into a single UserTaskRevisionConflictException, so a concurrent edit returns the documented revision-conflict result behind any provider instead of a 500. EF Core (SQLite, SQL Server, PostgreSQL, MySQL, Oracle) and VNext persistence, hosted due/reconciliation/delivery workers, docs, and 49 tests. Note: this branch also carries two commits inherited from its branch point that are not part of User Tasks and are squashed in here — the revert-version allocation change from #7917 (WorkflowDefinitionPublisher.RevertVersionAsync now allocates from the last version rather than the latest) and an NU1903 package pin. Merged deliberately rather than rebased out.
6.8 KiB
Implementation Plan: User Tasks
Feature: 013-user-tasks | Date: 2026-08-17 | Specification: spec.md
Summary
Deliver an identity-neutral human-task bounded context in Elsa Core and a reference task workbench in Elsa Studio. A blocking activity creates a materialized bookmark payload; post-commit projection creates a durable task record. Authorized REST commands atomically mutate task state and terminal commands asynchronously resume the bookmark. Reconciliation closes commit gaps. The core package defaults to in-memory persistence and optional provider packages mirror Elsa.Secrets.
Technical Context
Language/Version: C# latest; nullable and implicit usings enabled; Blazor/Razor in Studio
Primary Dependencies: Elsa feature/module and workflow runtime infrastructure, FastEndpoints via Elsa endpoint base types, mediator notifications, SignalR, Microsoft.Extensions.Options/Logging, ASP.NET Core Data Protection/rate limiting, EF Core provider packages
Storage: In-memory development/test repository; module-specific EF Core context and SQLite, SQL Server, PostgreSQL, MySQL, Oracle packages; VNext document-store adapter
Testing: xUnit, existing Elsa testing helpers, SQLite integration fixtures, Studio component/client tests where available
Targets: Core net8.0;net9.0;net10.0; existing Studio targets
Performance Envelope: approximately 100,000 open and millions of terminal tasks per tenant; cursor queries avoid protected JSON and page-number offsets
Constraints: no Elsa.Identity dependency; no change to generic RunTask; task/bookmark consistency across failure and cluster races; protected data never disclosed through summary/search/realtime
Repositories: Core worktree plus adjacent Elsa Studio repository; local-only delivery gates while GitHub is unavailable
Constitution Check
Pre-design
- Separate Core module, EF persistence, provider packages, and Studio module: PASS.
- Provider-neutral contracts and optional host integrations: PASS.
- Activity uses standard attributes and input/output wrappers: PASS.
- Endpoints remain one class per route and asynchronous: PASS.
- Public behavior and architecture are documented before code: PASS.
- Minimum scoped product: PASS; excluded capabilities are explicit.
Post-design
- No persistence or identity infrastructure leaks into domain/API contracts: PASS.
- Every durable race has a revision/idempotency rule and test task: PASS.
- Every protected-data path has an authorization/disclosure rule: PASS.
- Multi-provider persistence follows established Elsa.Secrets boundaries: PASS.
- Local build/test/review gates replace only the explicitly skipped GitHub gates: PASS.
Architecture
flowchart LR
A["UserTask activity"] -->|"bookmark payload"| B["Workflow commit"]
B --> C["Post-commit projector"]
C --> D["IUserTaskRepository"]
D --> E["In-memory / EF Core / VNext"]
F["Studio or host app"] --> G["Authorized REST endpoints"]
G --> H["IUserTaskManager"]
H --> D
H --> I["Identity and policy adapters"]
H --> J["Form and invitation adapters"]
H -->|"terminal operation"| K["Bookmark resumer"]
K --> A
L["Paged reconciler and due scanner"] --> D
L --> K
H --> M["Mediator lifecycle events"]
M --> N["Metadata-free SignalR invalidation"]
Package and File Shape
Elsa Core repository
src/modules/Elsa.UserTasks: activity, domain models, contracts, default services, in-memory repository, projection/reconciliation/due workers, permissions, notifications, SignalR hub, endpoints, feature and shell feature.src/modules/Elsa.UserTasks.Persistence.EFCore: context, configurations, repository, feature.src/modules/Elsa.UserTasks.Persistence.EFCore.{Sqlite,SqlServer,PostgreSql,MySql,Oracle}: provider configuration, migrations, shell features.src/modules/Elsa.UserTasks.Persistence.VNext: document-store-backed repository/feature.test/unit/Elsa.UserTasks.UnitTests: lifecycle, identity, disclosure, form, invitation, idempotency, projection, due, API model tests.test/integration/Elsa.UserTasks.IntegrationTestswhere an existing test project pattern supports endpoint/runtime integration.
Elsa Studio repository
src/modules/Elsa.Studio.UserTasks: remote feature, menu, Refit client, models, queue/detail pages and components, optional extension interfaces, guest page, realtime/polling coordinator.- Existing workflow designer renders the activity through metadata; custom inputs are added only where generic editing is insufficient.
Delivery Sequence
- Land the approved dossier, contracts, terminology, and traceable task ledger.
- Implement the domain, state machine, activity/bookmark contract, repository, and focused unit tests.
- Add post-commit projection, asynchronous completion, reconciliation, due processing, and lifecycle notifications.
- Add authorized REST query/commands and safe DTO mapping.
- Add invitations, guest sessions, delivery outbox, anonymous defenses, and tests.
- Add EF Core/VNext persistence and provider migrations/configuration.
- Add Studio queue/detail/designer/guest integrations.
- Run targeted then broad local verification, traceability analysis, and up to five self-review passes.
Verification Strategy
- Unit-test legal and illegal state transitions, exact revision increments, canonical idempotency payloads, claim and terminal races.
- Contract-test query authorization and safe/protected DTO mapping for every relationship.
- Runtime-test task projection after workflow commit, bookmark resume, finalization, and each reconciliation gap.
- SQLite-test durable restart, indexes, tenant isolation, cursor stability, and cleanup.
- Schema-review every provider migration and compile all provider projects.
- Studio-test tab queries, URL state, responsive route behavior, capability actions, conflict refresh, disclosure, realtime fallback, and accessibility semantics.
- Build affected projects first, then both repositories broadly without GitHub-dependent checks.
Risk Controls
- Dual-write inconsistency: bookmark is source evidence; projection happens post-commit and a paged reconciler repairs both directions.
- Authorization leakage: repository query accepts an authorization scope compiled by policy; summary DTOs cannot carry protected fields.
- Terminal duplicate resume: transitional states, expected revision, canonical operation record, and bookmark-removal finalization.
- Provider schema drift: one EF model plus provider-specific migrations and a shared conformance suite.
- Guest secret exposure: hash at rest, encrypted transient outbox, generic anonymous surface, short bounded sessions.
- Scope pressure: v1 exclusions remain acceptance constraints; standalone tasks, drafts, attachments, comments, bulk actions, and native forms are not implementation tasks.