Skip to content

Domain model

Everything hangs off the issue: a typed record in a project, with a parent for hierarchy, a status owned by a workflow, and a JSONB bag for custom fields. Every change writes a history row, which drives the activity stream, metrics (cycle time, time in status, burndowns) and the Jira importer's replay of the past.

Entities

Entity Purpose Key fields
Project Container for issues and configuration key (old keys kept as aliases), name, lead, template, open role or private
Issue type Epic, Story, Task, Bug, Sub-task (per project) key, name, hierarchy level (epic 1, standard 0, sub-task −1), icon, workflow
Issue The work item project, number, type, parent, status, workflow version, assignee, reporter, priority, rank, sprint, story points, estimates, dates, labels, resolution, custom fields (JSONB), version
Issue link Non-hierarchical relationships source, target, type (blocks, relates, duplicates, clones)
Field definition Custom fields key, type (text, number, select, multi-select, user, date, version, checkbox, URL), projects and types
Workflow, workflow version Versioned state machines YAML source and compiled definition; issues pin a version
Board, column Views over issues Scrum or Kanban, filter, columns → statuses, WIP limits, swimlanes, card fields
Sprint, release Time boxes and versions dates, goal, state; sprints snapshot what was committed and completed
Comment, attachment, watcher Collaboration Markdown body, file (PostgreSQL or S3), who follows the issue
Worklog Time spent issue, author, started at, duration
Issue history Append-only changelog issue, actor, field, from, to, time, and what acted ("via" an AI assistant)
Dev link Git artefacts tied to an issue provider, repository, kind (branch, commit, pull/merge request, pipeline), state, URL
Automation rule, run Rules and their history trigger, CEL condition, actions, target (issue, parent, children)
Dashboard Personal or shared gadgets gadget layout and configuration
User, group, role People and access source (SSO, SCIM, Google, Keycloak, local…), organisation role, groups mapped to roles, project and custom roles

Hierarchy

The rule is parent level = child level + 1, taken from the issue type: epics hold stories, tasks and bugs, which hold sub-tasks. The query language's epic field follows the epic ancestor, so sub-tasks count under their story's epic.

Issue keys

Each project has a counter, locked with SELECT … FOR UPDATE when an issue is created. When a project key is renamed, the old key is kept as an alias so keys in commit messages and links still resolve.

Ranking and concurrency

Boards and backlogs use fractional string ranks compared with COLLATE "C", so dragging a card updates one row. Every issue carries a version; an update with a stale version is refused with 409, so two people editing at once cannot overwrite each other silently.

Configuration

Project templates (Scrum, Kanban, Bug tracking, and the service desk) copy a workflow and a set of issue types into the project; workflows can then be changed per project and per issue type.