Tasks & Statuses

Tasks, the per-team triage queue, statuses, notes, and activity records in the Operation plugin.

Backend code lives under backend/plugins/operation_api/src/modules/{task,status,note,activity}/. The task module also contains the triage model and the task segment definitions in task/meta/segments/.

Task data model

operation_tasks (modules/task/db/definitions/task.ts):

FieldTypeNotes
name, descriptionstringname required
statusObjectIdreferences a team Status; required
teamIdObjectIdrequired; permission scope field
priority, estimatePointnumberpriority defaults 0; estimatePoint defaults 0
assigneeId, createdBystringCore user ids (indexed, sparse)
labelIds, tagIdsstring[]Core labels/tags
cycleId, projectId, milestoneIdObjectIdoptional rollups
startDate, targetDate, statusChangedDateDatestatusChangedDate determines "completed" reporting
number, statusTypenumberstatusType mirrors the status's type
githubIssueNumber, githubIssueUrl, githubRepoNameset by the GitHub sync
propertiesDatamixedoperation:task property values, keyed by field id
segmentIdsstring[]written only by the segmentation worker

Task _id is an ObjectId

taskSchema is a plain new Schema(...) without schemaWrapper, so _id stays a Mongo ObjectId. Segment and tRPC code always goes through the Mongoose model so string ids cast correctly. Do not bypass it with a raw driver handle.

Statuses

Status documents are team-scoped ({ name, description, color, type, teamId, order }). type is one of STATUS_TYPES (status/constants/types.ts): STARTED=1, UNSTARTED=2, BACKLOG=3, COMPLETED=4, CANCELLED=5, TRIAGE=6. Creating a team seeds the five default statuses (backlog, todo, in progress, done, cancelled); see status/utils.ts.

Triage queue

Triage items (operation_triage) are inbox work for a team: { name, description, teamId, createdBy, priority, status, number } plus GitHub issue fields. operationConvertTriageToTask creates a task in the same team (optionally looking up status by status type), carries over GitHub linkage, stores the reason as a note on the new task, and deletes the triage record.

operationCancelTriage is not implemented

operationCancelTriage(_id) is declared in the triage GraphQL schema but has no resolver; calling it errors at runtime. To retire a triage item, update its status with operationUpdateTriage or convert it with operationConvertTriageToTask (which deletes the record).

Queries and mutations

OperationKindPermission
getTasks(filter: ITaskFilter) / getTask(_id)querytaskRead
createTask(…) / updateTask(…) / removeTask(_id)mutationtaskCreate / taskUpdate / taskRemove
operationGetTriage(_id) / operationGetTriageList(filter)querytriageRead
operationAddTriage / operationUpdateTriagemutationtriageCreate / triageUpdate
operationConvertTriageToTask(_id, status: Int, reason)mutationtriageConvert
getStatus(_id) / getStatusesByType(type, teamId) / getStatusesChoicesByTeam(teamId)querystatusRead
addStatus / updateStatus / deleteStatusmutationstatusCreate / statusUpdate / statusRemove
getOperationActivities(contentId, …)querytaskRead
getNote(_id) / createNote / updateNote / deleteNotequery/mutationnoteRead / noteCreate / noteUpdate / noteRemove

ITaskFilter accepts status, priority, assigneeId, createdBy, cycleId, projectId, milestoneId, teamId, labelIds, tagIds, estimatePoint, statusType, cycleFilter (noCycle, anyPastCycle, previousCycle, currentCycle, upcomingCycle, anyFutureCycle), projectStatus/projectPriority/projectLeadId, date bounds, and cursor pagination params.

Example createTask call:

mutation {
  createTask(
    name: "Prepare release checklist"
    teamId: "team_1"
    status: "status_todo"
    assigneeId: "user_1"
    priority: 3
    estimatePoint: 5
  ) {
    _id
    name
  }
}

Notes and activity

Note ({ content, contentId, createdBy, mentions, statusId }) attaches to a task or project by contentId; mentions trigger a note notification to the mentioned users, and removeNote is author-only. OperationActivity ({ action, contentId, module, metadata: {newValue, previousValue}, createdBy }) is the audit trail; subscribe to operationActivityChanged(contentId) for live updates.

Subscriptions

operationTaskChanged(_id), operationTaskListChanged(filter: ITaskFilter) (filtered server-side via withFilter), and operationActivityChanged(contentId) publish on create/update through graphqlPubsub.

tRPC

Merged in src/trpc/init-trpc.ts:

ProcedureTypeNotes
task.tag({ tagIds, targetIds, type, action })mutationBulk-set tagIds on tasks
task.findOne({ _ids })queryFirst task among the ids ({ _id, name, teamId } or null); non-ObjectId ids skipped
task.createFromSource({ userId, doc })mutationCreates a task as userId; reads teamId from doc.status (must be a status ObjectId); publishes the task subscriptions; returns { _id }

createFromSource is how frontline converts a conversation into a task. It checks no permission; the caller must enforce taskCreate for the acting user.

"Status not found" from createFromSource

doc.status must be a status _id (ObjectId), not a status type number. Only operationConvertTriageToTask accepts a type.

Segments and import/export

  • operation:task.tasks is a segment content type with 19 filterable fields, member listing/counting, materialised segmentIds, and relations user.assignedTasks / user.createdTasks (the field-joined relations rely on the assigneeId/createdBy indexes). The content type must be exactly operation:task.tasks; the event dispatcher keys on it.
  • Import type operation:task.task (taskImportManage) and export types operation:task.task / operation:project.project (taskExportManage / projectExportManage) are registered via meta/import-export. Repeating property groups export as numbered <Group> <n> / <Field> columns.
  • Notifications: taskAssignee (task assigned) and taskStatus (status changed).

Permissions

Modules task, triage, note, status (and project, cycle, milestone, team elsewhere) use scoped permissions: own (records you created), group (records in your teams via scopeField: 'teamId'), all. Read actions are always: true; write actions are grantable. taskAssign is a custom action for assignment control.

Was this helpful?