feat: support multiple assignees for tasks#277
Merged
Conversation
- Replaced the single-valued `assignee_id` column in the `tasks` table with a new `task_assignees` join table to allow multiple assignees per task. - Updated the task creation and update services to handle multiple assignee IDs. - Modified the task filtering logic to accommodate multiple assignees. - Enhanced the HTTP transport layer to accept and return multiple assignee IDs in task requests and responses. - Updated the workflow consumer to manage task assignments with multiple assignees. - Added end-to-end tests to verify the functionality of multiple assignees in task management.
Contributor
There was a problem hiding this comment.
Important
Assignee grouping in board/table views is inconsistent with the new multi-assignee model: a task only appears under its first assignee's column, and dragging a task onto an assignee column replaces the entire assignee set. Decide the intended board behavior before merging.
Reviewed changes — migration from single assignee_id to a task_assignees join table across the API, service layer, automations, plugins, MCP client, and web UI.
- Migrated
tasks.assignee_idto atask_assigneesjoin table with backfill and idempotent DDL. - Replaced single-value assignee fields with
[]uuid.UUIDarrays in domain models, DTOs, and responses. - Updated task filtering, workflow automation, and notification events to work with the new array shape.
- Added a multi-user editor and avatar stacks for selecting/displaying multiple assignees.
ℹ️ Nitpicks
apps/e2e/tests/projects/interaction-views.spec.ts:88still typescreateTaskwithassignee_id?: string; the API now expectsassignee_ids, so the helper payload type should be updated to match even though no current caller uses it.
Kimi K2 (free via Pullfrog for OSS) | 𝕏
…y and preserve assignment history
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Summary
Tasks can now have multiple assignees instead of exactly one. Full-stack change spanning the schema, the Go API, the MCP server, and the web UI.
Data model
tasks.assignee_idcolumn with atask_assigneesjoin table (task_id,member_id,assigned_at), migrated via a backfill + column drop.DO $$ ... $$block checkinginformation_schema.columns) since this repo's migration runner has no applied-migrations tracking table — it re-executes every.sqlfile on every app startup, so a plain non-idempotent backfill/drop would fail on the second startup once the source column is already gone.Backend (
services/api)Task.AssigneeID *uuid.UUID→AssigneeIDs []uuid.UUIDacross the domain, repository, service, DTO, and handler layers.assignee_id/assignee_ids/assignee_id=nullquery params; filtering matches a task if any of its assignees is in the given set.CreateTask/UpdateTaskaccept/replace the full assignee set in one call (assignee_idsin the request body), following the same "send the full new value" convention already used fortags.assignee_iddirectly and would otherwise have silently broken: the WASM plugin runtime'spaca.tasks_list/paca.task_gethost functions, and the MCP server (apps/mcp) REST client + task formatters.Frontend (
apps/web)multi-userproperty-field mode (chip list + checklist popover) for editing assignees in the task detail panel.+Noverflow badge) and a toggle-based picker instead of a single-select popover.Docs
assignee_ids.Known scope boundary
MCP tools (
create_task/update_task) still assign one member per call — the client translates that into a single-elementassignee_idsarray on the wire. Multi-assign-in-one-call for AI agents was left out of scope.Test plan
go build ./... && go vet ./... && go test ./...inservices/apiPACA_E2E=1 go test ./test/e2e/...— full suite, including a newTestE2ETaskManagement_MultipleAssignees(create/get/filter/partial-update/clear) and the workflow-automation e2e tests updated for replace semanticsbun run lint && bun run tsc -b && bun run testinapps/web— 281 tests passingbun run lint && npx tsc --noEmit && bun run testinapps/mcp— 605 tests passing