---
title: "Project"
description: "Projects and tasks. Plan work as projects, milestones and tasks with assignees and deadlines."
canonical: "https://obop.dev/apps/projects/"
lang: "en"
---

# Project

## What it is for

Plan work as projects, milestones and tasks with assignees and deadlines. Progress is tracked by status, which keeps the model simple; it is a good fit for small teams that want a shared board rather than effort accounting.

## What the package does and does not do

Projects, milestones and tasks with assignees, deadlines and status flows. Progress is tracked by status, not computed from task effort.

## Models

### `projects_project`

A body of work with a goal

Read group: `projects.user`. Write group: `projects.manager`.

| Field | Kind | Data class | Personal data | Group | Agents see | Description |
|---|---|---|---|---|---|---|
| `name` | text | `none` | no | `projects.user` | in clear | Project name |
| `code` | text | `none` | no | `projects.user` | in clear | Short reference used in reports, for example WEB-24 |
| `project_manager` | text | `internal` | yes | `projects.user` | masked | Name of the person accountable for the project |
| `start_on` | date | `none` | no | `projects.user` | in clear | Planned start date (YYYY-MM-DD) |
| `deadline` | date | `none` | no | `projects.user` | in clear | Date the project must be finished (YYYY-MM-DD) |
| `budget` | money | `none` | no | `projects.user` | in clear | Agreed budget for the project (minor currency units, e.g. cents) |
| `description` | longtext | `none` | no | `projects.user` | in clear | Goal and scope of the project |
| `state` | select (planned, active, done) | `none` | no | `projects.user` | in clear | Project status: planned, active, done |

### `projects_milestone`

A checkpoint in a project

Read group: `projects.user`. Write group: `projects.manager`.

| Field | Kind | Data class | Personal data | Group | Agents see | Description |
|---|---|---|---|---|---|---|
| `project_id` | ref → projects_project | `none` | no | `projects.user` | in clear | The project the milestone belongs to |
| `name` | text | `none` | no | `projects.user` | in clear | Milestone name, for example Design approved |
| `due_on` | date | `none` | no | `projects.user` | in clear | Date the milestone is due (YYYY-MM-DD) |
| `description` | longtext | `none` | no | `projects.user` | in clear | What must be true for the milestone to count as reached |
| `state` | select (pending, reached, missed) | `none` | no | `projects.user` | in clear | Milestone status: pending, reached, missed |

### `projects_task`

A unit of work inside a project

Read group: `projects.user`. Write group: `projects.user`.

| Field | Kind | Data class | Personal data | Group | Agents see | Description |
|---|---|---|---|---|---|---|
| `title` | text | `none` | no | `projects.user` | in clear | What needs doing |
| `project_id` | ref → projects_project | `none` | no | `projects.user` | in clear | The project this task belongs to; empty for a private task |
| `milestone_id` | ref → projects_milestone | `none` | no | `projects.user` | in clear | The milestone this task contributes to |
| `assignee` | text | `internal` | yes | `projects.user` | masked | Name of the person responsible |
| `priority` | select (low, normal, high) | `none` | no | `projects.user` | in clear | How important the task is: low, normal, high |
| `due_on` | date | `none` | no | `projects.user` | in clear | Date the task is due (YYYY-MM-DD) |
| `estimate_minutes` | number | `none` | no | `projects.user` | in clear | Planned effort in minutes |
| `description` | longtext | `none` | no | `projects.user` | in clear | Details, acceptance criteria and links |
| `state` | select (todo, doing, done, cancelled) | `none` | no | `projects.user` | in clear | Task status: todo, doing, done, cancelled |

## Workflows

### `projects_project`

| Action | Moves | Who may run it | Approval |
|---|---|---|---|
| `projects_project.start` | state: planned → active | `projects.manager` | no |
| `projects_project.finish` | state: active → done | `projects.manager` | no |
| `projects_project.reopen` | state: done → active | `projects.manager` | no |

### `projects_milestone`

| Action | Moves | Who may run it | Approval |
|---|---|---|---|
| `projects_milestone.reach` | state: pending → reached | `projects.manager` | no |
| `projects_milestone.miss` | state: pending → missed | `projects.manager` | no |

### `projects_task`

| Action | Moves | Who may run it | Approval |
|---|---|---|---|
| `projects_task.begin` | state: todo → doing | `projects.user` | no |
| `projects_task.complete` | state: doing → done | `projects.user` | no |
| `projects_task.cancel` | state: todo → cancelled | `projects.user` | no |

## Permission groups

Groups used by this app:

- `projects.manager`
- `projects.user`

## Approval steps

No step in this app needs an approval, apart from deleting records.

## What agents can and cannot do

An agent can read, search, create and update records of this app, and run the actions that need no approval, within the permission groups of its token.

It can only propose these steps, and a person must approve them: `projects_project.delete`, `projects_milestone.delete`, `projects_task.delete`.

Personal data is masked as placeholder tokens: `projects_project.project_manager`, `projects_task.assignee`.

## Dependencies

None.

## Install

Install it from the Customize app (Marketplace), or from the command line:

```bash
obop modules install-from projects
```

Needs a database and administrator rights.

## Build your own

[The module guide shows how apps like this one are written](/docs/reference/module-manifest/)
