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.
105 lines
6.8 KiB
Markdown
105 lines
6.8 KiB
Markdown
# Implementation Plan: User Tasks
|
|
|
|
**Feature**: `013-user-tasks` | **Date**: 2026-08-17 | **Specification**: [spec.md](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
|
|
|
|
```mermaid
|
|
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.IntegrationTests` where 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
|
|
|
|
1. Land the approved dossier, contracts, terminology, and traceable task ledger.
|
|
2. Implement the domain, state machine, activity/bookmark contract, repository, and focused unit tests.
|
|
3. Add post-commit projection, asynchronous completion, reconciliation, due processing, and lifecycle notifications.
|
|
4. Add authorized REST query/commands and safe DTO mapping.
|
|
5. Add invitations, guest sessions, delivery outbox, anonymous defenses, and tests.
|
|
6. Add EF Core/VNext persistence and provider migrations/configuration.
|
|
7. Add Studio queue/detail/designer/guest integrations.
|
|
8. 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.
|